11 import xml
.etree
.ElementTree
as ElementTree
14 import elementtree
.ElementTree
as ElementTree
16 warnings
.warn('Python 2.5 or higher or elementtree is needed to use the TivoPush')
18 if 'ElementTree' not in locals():
21 def __init__(self
, *arg
, **karg
):
22 raise Exception('Python 2.5 or higher or elementtree is needed to use the TivoPush')
27 def __init__(self
, username
, password
, debug
=False):
28 self
.__username
= username
29 self
.__password
= password
33 self
.__cj
= cookielib
.CookieJar()
34 self
.__opener
= urllib2
.build_opener(urllib2
.HTTPSHandler(debuglevel
=1), urllib2
.HTTPCookieProcessor(self
.__cj
))
38 if not self
.__pcBodySearch
():
39 self
.__pcBodyStore
('pyTivo', True)
41 def pushVideo(self
, tsn
, url
, description
='test', duration
='40000', size
='3000000', title
='test', subtitle
='test'):
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
)
48 def bodyOfferSchedule(self
, pc_body_id
):
50 data
= {'pcBodyId' : pc_body_id
,}
52 '/Steph%27s%20Videos/The%20Fairly%20Odd%20Parents%20-%20Channel%20Chasers.xvid-pyro.avi',
54 {'Content-Type' : 'x-tivo/dict-binary'}
56 result
= self
.__opener
.open(r
)
58 self
.__log
('bodyOfferSchedule\n%s\n\n%sg' % (data
, result
))
62 def __log(self
, message
):
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'
78 'https://mind.tivo.com:8181/mind/login',
79 urllib
.urlencode(data
)
82 result
= self
.__opener
.open(r
)
86 self
.__log
('__login\n%s' % (data
))
88 def __bodyOfferModify(self
, tsn
, pc_body_id
, description
, duration
, size
, title
, subtitle
, url
):
91 'bodyId' : 'tsn:' + tsn
,
92 'description' : description
,
93 'duration' : duration
,
94 'encodingType' : 'mpeg2ProgramStream',
95 'partnerId' : 'tivo:pt.3187',
96 'pcBodyId' : pc_body_id
,
97 'publishDate' : time
.strftime('%Y-%m-%d %H:%M%S', time
.gmtime()),
99 'source' : 'file:/C%3A%2FDocuments%20and%20Settings%2FStephanie%2FDesktop%2FVideo',
100 'state' : 'complete',
101 'subtitle' : subtitle
,
106 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferModify&bodyId=tsn:' + tsn
,
108 {'Content-Type' : 'x-tivo/dict-binary'}
110 result
= self
.__opener
.open(r
)
112 xml
= ElementTree
.parse(result
).find('.')
114 self
.__log
('__bodyOfferModify\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
116 if xml
.findtext('state') != 'complete':
117 raise Exception(ElementTree
.tostring(xml
))
119 offer_id
= xml
.findtext('offerId')
120 content_id
= offer_id
.replace('of','ct')
122 return offer_id
, content_id
125 def __subscribe(self
, offer_id
, content_id
, tsn
):
127 'bodyId' : 'tsn:' + tsn
,
129 'contentId': content_id
,
130 'offerId' : offer_id
,
131 'type' : 'singleOfferSource',
133 'title' : 'pcBodySubscription',
138 'https://mind.tivo.com:8181/mind/mind7?type=subscribe&bodyId=tsn:' + tsn
,
140 {'Content-Type' : 'x-tivo/dict-binary'}
142 result
= self
.__opener
.open(r
)
144 xml
= ElementTree
.parse(result
).find('.')
146 self
.__log
('__subscribe\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
150 def __pcBodySearch(self
):
154 'https://mind.tivo.com:8181/mind/mind7?type=pcBodySearch',
156 {'Content-Type' : 'x-tivo/dict-binary'}
158 result
= self
.__opener
.open(r
)
160 xml
= ElementTree
.parse(result
).find('.')
163 self
.__log
('__pcBodySearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
165 return [id.text
for id in xml
.findall('pcBody/pcBodyId')]
167 def __collectionIdSearch(self
, url
):
171 'https://mind.tivo.com:8181/mind/mind7?type=collectionIdSearch',
173 {'Content-Type' : 'x-tivo/dict-binary'}
175 result
= self
.__opener
.open(r
)
177 xml
= ElementTree
.parse( result
).find('.')
178 collection_id
= xml
.findtext('collectionId')
180 self
.__log
('__collectionIdSearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
184 def __pcBodyStore(self
, name
, replace
=False):
188 'replaceExisting' : str(replace
).lower(),
192 'https://mind.tivo.com:8181/mind/mind7?type=pcBodyStore',
194 {'Content-Type' : 'x-tivo/dict-binary'}
196 result
= self
.__opener
.open(r
)
198 xml
= ElementTree
.parse(result
).find('.')
200 self
.__log
('__pcBodySearch\n%s\n\n%s' % (data
, ElementTree
.tostring(xml
)))
206 """Helper to create x-tivo/dict-binary"""
209 keys
= [str(k
) for k
in d
]
215 output
.append( varint( len(k
) ) )
218 if isinstance(v
, dict):
219 output
.append( struct
.pack('>B', 0x02) )
220 output
.append( dictcode(v
) )
224 output
.append( struct
.pack('>B', 0x01) )
225 output
.append( varint( len(v
) ) )
228 output
.append( struct
.pack('>B', 0x00) )
230 output
.append( struct
.pack('>B', 0x80) )
232 return ''.join(output
)
239 bits
.append(i
& 0x01)
252 for bit
, p
in zip(mybits
, itertools
.count()):
253 byte
+= bit
* (2 ** p
)
257 output
[-1] = output
[-1] |
0x80
258 return ''.join([chr(b
) for b
in output
])