Changeset 5027df9739e905098ee65f26d8229a9c55f84925
- Timestamp:
- 04/06/08 00:54:26 (8 months ago)
- git-parent:
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
mind.py
r4574b4f r5027df9 3 3 import urllib 4 4 import struct 5 import httplib 5 import httplib 6 6 import time 7 7 import warnings 8 8 import itertools 9 import config 9 10 10 11 try: 11 import xml.etree.ElementTree as ElementTree 12 import xml.etree.ElementTree as ElementTree 12 13 except ImportError: 13 14 try: … … 15 16 except ImportError: 16 17 warnings.warn('Python 2.5 or higher or elementtree is needed to use the TivoPush') 17 18 18 19 if 'ElementTree' not in locals(): 19 20 … … 21 22 def __init__(self, *arg, **karg): 22 23 raise Exception('Python 2.5 or higher or elementtree is needed to use the TivoPush') 23 24 24 25 else: 25 26 … … 27 28 def __init__(self, username, password, debug=False): 28 29 self.__username = username 29 self.__password = password 30 self.__password = password 30 31 31 32 self.__debug = debug … … 39 40 self.__pcBodyStore('pyTivo', True) 40 41 41 def pushVideo(self, tsn, url, description='test', duration='40000', size='3000000', title='test', subtitle='test'): 42 43 # It looks like tivo only supports one pc per house 44 pc_body_id = self.__pcBodySearch()[0] 45 offer_id, content_id = self.__bodyOfferModify(tsn, pc_body_id, description, duration, size, title, subtitle, url) 46 self.__subscribe(offer_id, content_id, tsn) 47 48 def bodyOfferSchedule(self, pc_body_id): 49 50 data = {'pcBodyId' : pc_body_id,} 51 r = urllib2.Request( 52 '/Steph%27s%20Videos/The%20Fairly%20Odd%20Parents%20-%20Channel%20Chasers.xvid-pyro.avi', 53 dictcode(data), 54 {'Content-Type' : 'x-tivo/dict-binary'} 55 ) 56 result = self.__opener.open(r) 57 58 self.__log('bodyOfferSchedule\n%s\n\n%sg' % (data, result)) 59 60 return result.read() 61 62 def __log(self, message): 63 if self.__debug: 64 print message 65 print 66 67 def __login(self): 68 69 data = { 70 'cams_security_domain' : 'tivocom', 71 'cams_login_config' : 'http', 72 'cams_cb_username' : self.__username, 73 'cams_cb_password' : self.__password, 74 'cams_original_url' : '/mind/mind7?type=infoGet' 75 } 76 77 r = urllib2.Request( 78 'https://mind.tivo.com:8181/mind/login', 79 urllib.urlencode(data) 80 ) 81 try: 82 result = self.__opener.open(r) 83 except: 84 pass 85 86 self.__log('__login\n%s' % (data)) 87 88 def __bodyOfferModify(self, tsn, pc_body_id, description, duration, size, title, subtitle, url): 89 42 def pushVideo(self, tsn, url, description, duration, size, title, subtitle): 90 43 data = { 91 44 'bodyId' : 'tsn:' + tsn, … … 103 56 'url' : url, 104 57 } 105 r = urllib2.Request( 106 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferModify&bodyId=tsn:' + tsn, 107 dictcode(data), 108 {'Content-Type' : 'x-tivo/dict-binary'} 109 ) 110 result = self.__opener.open(r) 111 112 xml = ElementTree.parse(result).find('.') 113 58 59 # It looks like tivo only supports one pc per house 60 pc_body_id = self.__pcBodySearch()[0] 61 offer_id, content_id = self.__bodyOfferModify(data) 62 self.__subscribe(offer_id, content_id, tsn) 63 64 def getDownloadRequests(self): 65 NEEDED_VALUES = [ 66 'bodyId', 67 'bodyOfferId', 68 'description', 69 'partnerId', 70 'pcBodyId', 71 'publishDate', 72 'source', 73 'state', 74 'subscriptionId', 75 'subtitle', 76 'title', 77 'url', 78 ] 79 80 # It looks like tivo only supports one pc per house 81 pc_body_id = self.__pcBodySearch()[0] 82 83 requests = [] 84 offer_list = self.__bodyOfferSchedule(pc_body_id) 85 86 for offer in offer_list.findall('bodyOffer'): 87 d = {} 88 if offer.findtext('state') != 'scheduled': 89 continue 90 91 for n in NEEDED_VALUES: 92 d[n] = offer.findtext(n) 93 requests.append(d) 94 95 return requests 96 97 def completeDownloadRequest(self, request): 98 request['encodingType'] = 'mpeg2ProgramStream' 99 request['state'] = 'complete' 100 request['type'] = 'bodyOfferModify' 101 request['updateDate'] = time.strftime('%Y-%m-%d %H:%M%S', time.gmtime()) 102 103 offer_id, content_id = self.__bodyOfferModify(request) 104 self.__subscribe(offer_id, content_id, request['bodyId'][4:]) 105 106 107 def getXMPPLoginInfo(self): 108 # It looks like tivo only supports one pc per house 109 pc_body_id = self.__pcBodySearch()[0] 110 111 xml = self.__bodyXmppInfoGet(pc_body_id) 112 113 results = {} 114 results['server'] = xml.findtext('server') 115 results['port'] = int(xml.findtext('port')) 116 results['username'] = xml.findtext('xmppId') 117 118 for sendPresence in xml.findall('sendPresence'): 119 results.setdefault('presence_list', []).append(sendPresence.text) 120 121 return results 122 123 def __log(self, message): 124 if self.__debug: 125 print message 126 print 127 128 def __login(self): 129 130 data = { 131 'cams_security_domain' : 'tivocom', 132 'cams_login_config' : 'http', 133 'cams_cb_username' : self.__username, 134 'cams_cb_password' : self.__password, 135 'cams_original_url' : '/mind/mind7?type=infoGet' 136 } 137 138 r = urllib2.Request( 139 'https://mind.tivo.com:8181/mind/login', 140 urllib.urlencode(data) 141 ) 142 try: 143 result = self.__opener.open(r) 144 except: 145 pass 146 147 self.__log('__login\n%s' % (data)) 148 149 def __bodyOfferModify(self, data): 150 """Create an offer""" 151 r = urllib2.Request( 152 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferModify&bodyId=' + data['bodyId'], 153 dictcode(data), 154 {'Content-Type' : 'x-tivo/dict-binary'} 155 ) 156 result = self.__opener.open(r) 157 158 xml = ElementTree.parse(result).find('.') 159 114 160 self.__log('__bodyOfferModify\n%s\n\n%sg' % (data, ElementTree.tostring(xml))) 115 161 … … 124 170 125 171 def __subscribe(self, offer_id, content_id, tsn): 172 """Push the offer to the tivo""" 126 173 data = { 127 174 'bodyId' : 'tsn:' + tsn, … … 134 181 'uiType' : 'cds', 135 182 } 136 137 r = urllib2.Request( 138 'https://mind.tivo.com:8181/mind/mind7?type=subscribe&bodyId=tsn:' + tsn, 183 184 r = urllib2.Request( 185 'https://mind.tivo.com:8181/mind/mind7?type=subscribe&bodyId=tsn:' + tsn, 139 186 dictcode(data), 140 187 {'Content-Type' : 'x-tivo/dict-binary'} … … 148 195 return xml 149 196 197 def __bodyOfferSchedule(self, pc_body_id): 198 """Get pending stuff for this pc""" 199 200 data = {'pcBodyId' : pc_body_id,} 201 r = urllib2.Request( 202 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferSchedule', 203 dictcode(data), 204 {'Content-Type' : 'x-tivo/dict-binary'} 205 ) 206 result = self.__opener.open(r) 207 208 xml = ElementTree.parse(result).find('.') 209 210 self.__log('bodyOfferSchedule\n%s\n\n%sg' % (data, ElementTree.tostring(xml))) 211 212 return xml 213 150 214 def __pcBodySearch(self): 215 """Find PCS""" 151 216 152 217 data = {} 153 218 r = urllib2.Request( 154 'https://mind.tivo.com:8181/mind/mind7?type=pcBodySearch', 219 'https://mind.tivo.com:8181/mind/mind7?type=pcBodySearch', 155 220 dictcode(data), 156 221 {'Content-Type' : 'x-tivo/dict-binary'} … … 166 231 167 232 def __collectionIdSearch(self, url): 233 """Find collection ids""" 168 234 169 235 data = {'url' : url} 170 236 r = urllib2.Request( 171 'https://mind.tivo.com:8181/mind/mind7?type=collectionIdSearch', 237 'https://mind.tivo.com:8181/mind/mind7?type=collectionIdSearch', 172 238 dictcode(data), 173 239 {'Content-Type' : 'x-tivo/dict-binary'} … … 183 249 184 250 def __pcBodyStore(self, name, replace=False): 185 251 """Setup a new PC""" 252 186 253 data = { 187 254 'name' : name, … … 190 257 191 258 r = urllib2.Request( 192 'https://mind.tivo.com:8181/mind/mind7?type=pcBodyStore', 193 dictcode(data), 259 'https://mind.tivo.com:8181/mind/mind7?type=pcBodyStore', 260 dictcode(data), 194 261 {'Content-Type' : 'x-tivo/dict-binary'} 195 262 ) … … 199 266 200 267 self.__log('__pcBodySearch\n%s\n\n%s' % (data, ElementTree.tostring(xml))) 268 269 return xml 270 271 def __bodyXmppInfoGet(self, body_id): 272 273 data = { 274 'bodyId' : body_id, 275 } 276 277 r = urllib2.Request( 278 'https://mind.tivo.com:8181/mind/mind7?type=bodyXmppInfoGet&bodyId=' + body_id, 279 dictcode(data), 280 {'Content-Type' : 'x-tivo/dict-binary'} 281 ) 282 283 result = self.__opener.open(r) 284 285 xml = ElementTree.parse(result).find('.') 286 287 self.__log('__bodyXmppInfoGe\n%s\n\n%s' % (data, ElementTree.tostring(xml))) 201 288 202 289 return xml … … 221 308 222 309 else: 223 v = str(v)310 v = unicode(v).encode('utf-8') 224 311 output.append( struct.pack('>B', 0x01) ) 225 output.append( varint( len(v) ) ) 312 output.append( varint( len(v) ) ) 226 313 output.append( v ) 227 314 … … 239 326 bits.append(i & 0x01) 240 327 i = i >> 1 241 328 242 329 if not bits: 243 330 output = [0] … … 249 336 mybits = bits[:7] 250 337 del bits[:7] 251 338 252 339 for bit, p in zip(mybits, itertools.count()): 253 340 byte += bit * (2 ** p) … … 258 345 return ''.join([chr(b) for b in output]) 259 346 347 348 def getMind(): 349 username = config.getTivoUsername() 350 password = config.getTivoPassword() 351 352 if not username or not password: 353 raise Exception("tivo_username and tivo_password required") 354 355 m = Mind(username, password, True) 356 357 return m 358
