10 import xml
.etree
.ElementTree
as ElementTree
13 import elementtree
.ElementTree
as ElementTree
15 warnings
.warn('Python 2.5 or higher or elementtree is needed to use the TivoPush')
17 if 'ElementTree' not in locals():
20 def __init__(self
, *arg
, **karg
):
21 raise Exception('Python 2.5 or higher or elementtree is needed to use the TivoPush')
26 def __init__(self
, username
, password
, debug
=False):
27 self
.__username
= username
28 self
.__password
= password
32 self
.__cj
= cookielib
.CookieJar()
33 self
.__opener
= urllib2
.build_opener(urllib2
.HTTPSHandler(debuglevel
=1), urllib2
.HTTPCookieProcessor(self
.__cj
))
37 if not self
.__pcBodySearch
():
38 self
.__pcBodyStore
('pyTivo', True)
40 def pushVideo(self
, tsn
, url
, description
='test', duration
='40000', size
='3000000', title
='test', subtitle
='test'):
42 # It looks like tivo only supports one pc per house
43 pc_body_id
= self
.__pcBodySearch
()[0]
44 offer_id
, content_id
= self
.__bodyOfferModify
(tsn
, pc_body_id
, description
, duration
, size
, title
, subtitle
, url
)
45 self
.__subscribe
(offer_id
, content_id
, tsn
)
47 def bodyOfferSchedule(self
, pc_body_id
):
49 data
= {'pcBodyId' : pc_body_id
,}
51 '/Steph%27s%20Videos/The%20Fairly%20Odd%20Parents%20-%20Channel%20Chasers.xvid-pyro.avi',
53 {'Content-Type' : 'x-tivo/dict-binary'}
55 result
= self
.__opener
.open(r
)
57 self
.__log
('bodyOfferSchedule\n%s\n\n%sg' % (data
, result
))
61 def __log(self
, message
):
69 'cams_security_domain' : 'tivocom',
70 'cams_login_config' : 'http',
71 'cams_cb_username' : self
.__username
,
72 'cams_cb_password' : self
.__password
,
73 'cams_original_url' : '/mind/mind7?type=infoGet'
77 'https://mind.tivo.com:8181/mind/login',
78 urllib
.urlencode(data
)
81 result
= self
.__opener
.open(r
)
85 self
.__log
('__login\n%s' % (data
))
87 def __bodyOfferModify(self
, tsn
, pc_body_id
, description
, duration
, size
, title
, subtitle
, url
):
90 'bodyId' : 'tsn:' + tsn
,
91 'description' : description
,
92 'duration' : duration
,
93 'encodingType' : 'mpeg2ProgramStream',
94 'partnerId' : 'tivo:pt.3187',
95 'pcBodyId' : pc_body_id
,
96 'publishDate' : time
.strftime('%Y-%m-%d %H:%M%S', time
.gmtime()),
98 'source' : 'file:/C%3A%2FDocuments%20and%20Settings%2FStephanie%2FDesktop%2FVideo',
100 'subtitle' : subtitle
,
105 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferModify&bodyId=tsn:' + tsn
,
107 {'Content-Type' : 'x-tivo/dict-binary'}
109 result
= self
.__opener
.open(r
)
111 xml
= ElementTree
.parse(result
).find('.')
113 self
.__log
('__bodyOfferModify\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
115 if xml
.findtext('state') != 'complete':
116 raise Exception(ElementTree
.tostring(xml
))
118 offer_id
= xml
.findtext('offerId')
119 content_id
= offer_id
.replace('of','ct')
121 return offer_id
, content_id
124 def __subscribe(self
, offer_id
, content_id
, tsn
):
126 'bodyId' : 'tsn:' + tsn
,
128 'contentId': content_id
,
129 'offerId' : offer_id
,
130 'type' : 'singleOfferSource',
132 'title' : 'pcBodySubscription',
137 'https://mind.tivo.com:8181/mind/mind7?type=subscribe&bodyId=tsn:' + tsn
,
139 {'Content-Type' : 'x-tivo/dict-binary'}
141 result
= self
.__opener
.open(r
)
143 xml
= ElementTree
.parse(result
).find('.')
145 self
.__log
('__subscribe\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
149 def __pcBodySearch(self
):
153 'https://mind.tivo.com:8181/mind/mind7?type=pcBodySearch',
155 {'Content-Type' : 'x-tivo/dict-binary'}
157 result
= self
.__opener
.open(r
)
159 xml
= ElementTree
.parse(result
).find('.')
162 self
.__log
('__pcBodySearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
164 return [id.text
for id in xml
.findall('pcBody/pcBodyId')]
166 def __collectionIdSearch(self
, url
):
170 'https://mind.tivo.com:8181/mind/mind7?type=collectionIdSearch',
172 {'Content-Type' : 'x-tivo/dict-binary'}
174 result
= self
.__opener
.open(r
)
176 xml
= ElementTree
.parse( result
).find('.')
177 collection_id
= xml
.findtext('collectionId')
179 self
.__log
('__collectionIdSearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
183 def __pcBodyStore(self
, name
, replace
=False):
187 'replaceExisting' : str(replace
).lower(),
191 'https://mind.tivo.com:8181/mind/mind7?type=pcBodyStore',
193 {'Content-Type' : 'x-tivo/dict-binary'}
195 result
= self
.__opener
.open(r
)
197 xml
= ElementTree
.parse(result
).find('.')
199 self
.__log
('__pcBodySearch\n%s\n\n%s' % (data
, ElementTree
.tostring(xml
)))
205 """Helper to create x-tivo/dict-binary"""
208 keys
= [str(k
) for k
in d
]
215 output
.append( struct
.pack('>B', l
) )
218 if isinstance(v
, dict):
219 output
.append( struct
.pack('>B', 0x02) )
220 output
.append( dictcode(v
) )
224 output
.append( struct
.pack('>B', 0x01) )
226 output
.append( struct
.pack('>B', l
) )
229 output
.append( struct
.pack('>B', 0x00) )
231 output
.append( struct
.pack('>B', 0x80) )
233 return ''.join(output
)
236 if __name__
== '__main__':
237 username
= 'armooo@armooo.net'
238 password
= 'in(into)'
239 tsn
= '6520001802C0F2A'
240 url
= 'http://10.0.1.52:9032/Steph%27s%20Videos/Weekend%20%28Godard%201967%29.avi'
242 mind
= Mind(username
, password
, True)
243 mind
.pushVideo(tsn
, url
)