6 import xml
.etree
.ElementTree
as ElementTree
11 def __init__(self
, username
, password
, debug
=False):
12 self
.__username
= username
13 self
.__password
= password
17 self
.__cj
= cookielib
.CookieJar()
18 self
.__opener
= urllib2
.build_opener(urllib2
.HTTPSHandler(debuglevel
=1), urllib2
.HTTPCookieProcessor(self
.__cj
))
22 if not self
.__pcBodySearch
():
23 self
.__pcBodyStore
('pyTivo', True)
25 def pushVideo(self
, tsn
, url
, description
='test', duration
='40000', size
='3000000', title
='test', subtitle
='test'):
27 # It looks like tivo only supports one pc per house
28 pc_body_id
= self
.__pcBodySearch
()[0]
29 offer_id
, content_id
= self
.__bodyOfferModify
(tsn
, pc_body_id
, description
, duration
, size
, title
, subtitle
, url
)
30 self
.__subscribe
(offer_id
, content_id
, tsn
)
32 def bodyOfferSchedule(self
, pc_body_id
):
34 data
= {'pcBodyId' : pc_body_id
,}
36 '/Steph%27s%20Videos/The%20Fairly%20Odd%20Parents%20-%20Channel%20Chasers.xvid-pyro.avi',
38 {'Content-Type' : 'x-tivo/dict-binary'}
40 result
= self
.__opener
.open(r
)
42 self
.__log
('bodyOfferSchedule\n%s\n\n%sg' % (data
, result
))
46 def __log(self
, message
):
54 'cams_security_domain' : 'tivocom',
55 'cams_login_config' : 'http',
56 'cams_cb_username' : self
.__username
,
57 'cams_cb_password' : self
.__password
,
58 'cams_original_url' : '/mind/mind7?type=infoGet'
62 'https://mind.tivo.com:8181/mind/login',
63 urllib
.urlencode(data
)
66 result
= self
.__opener
.open(r
)
70 self
.__log
('__login\n%s' % (data
))
72 def __bodyOfferModify(self
, tsn
, pc_body_id
, description
, duration
, size
, title
, subtitle
, url
):
75 'bodyId' : 'tsn:' + tsn
,
76 'description' : description
,
77 'duration' : duration
,
78 'encodingType' : 'mpeg2ProgramStream',
79 'partnerId' : 'tivo:pt.3187',
80 'pcBodyId' : pc_body_id
,
81 'publishDate' : time
.strftime('%Y-%m-%d %H:%M%S', time
.gmtime()),
83 'source' : 'file:/C%3A%2FDocuments%20and%20Settings%2FStephanie%2FDesktop%2FVideo',
85 'subtitle' : subtitle
,
90 'https://mind.tivo.com:8181/mind/mind7?type=bodyOfferModify&bodyId=tsn:' + tsn
,
92 {'Content-Type' : 'x-tivo/dict-binary'}
94 result
= self
.__opener
.open(r
)
96 xml
= ElementTree
.parse(result
).find('.')
98 if xml
.findtext('state') != 'complete':
99 raise Exception(ElementTree
.tostring(xml
))
101 offer_id
= xml
.findtext('offerId')
102 content_id
= offer_id
.replace('of','ct')
104 self
.__log
('__bodyOfferModify\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
105 return offer_id
, content_id
108 def __subscribe(self
, offer_id
, content_id
, tsn
):
110 'bodyId' : 'tsn:' + tsn
,
112 'contentId': content_id
,
113 'offerId' : offer_id
,
114 'type' : 'singleOfferSource',
116 'title' : 'pcBodySubscription',
121 'https://mind.tivo.com:8181/mind/mind7?type=subscribe&bodyId=tsn:' + tsn
,
123 {'Content-Type' : 'x-tivo/dict-binary'}
125 result
= self
.__opener
.open(r
)
127 xml
= ElementTree
.parse(result
).find('.')
129 self
.__log
('__subscribe\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
133 def __pcBodySearch(self
):
137 'https://mind.tivo.com:8181/mind/mind7?type=pcBodySearch',
139 {'Content-Type' : 'x-tivo/dict-binary'}
141 result
= self
.__opener
.open(r
)
143 xml
= ElementTree
.parse(result
).find('.')
146 self
.__log
('__pcBodySearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
148 return [id.text
for id in xml
.findall('pcBody/pcBodyId')]
150 def __collectionIdSearch(self
, url
):
154 'https://mind.tivo.com:8181/mind/mind7?type=collectionIdSearch',
156 {'Content-Type' : 'x-tivo/dict-binary'}
158 result
= self
.__opener
.open(r
)
160 xml
= ElementTree
.parse( result
).find('.')
161 collection_id
= xml
.findtext('collectionId')
163 self
.__log
('__collectionIdSearch\n%s\n\n%sg' % (data
, ElementTree
.tostring(xml
)))
167 def __pcBodyStore(self
, name
, replace
=False):
171 'replaceExisting' : str(replace
).lower(),
175 'https://mind.tivo.com:8181/mind/mind7?type=pcBodyStore',
177 {'Content-Type' : 'x-tivo/dict-binary'}
179 result
= self
.__opener
.open(r
)
181 xml
= ElementTree
.parse(result
).find('.')
183 self
.__log
('__pcBodySearch\n%s\n\n%s' % (data
, ElementTree
.tostring(xml
)))
189 """Helper to create x-tivo/dict-binary"""
192 keys
= [str(k
) for k
in d
]
199 output
.append( struct
.pack('>B', l
) )
202 if isinstance(v
, dict):
203 output
.append( struct
.pack('>B', 0x02) )
204 output
.append( dictcode(v
) )
208 output
.append( struct
.pack('>B', 0x01) )
210 output
.append( struct
.pack('>B', l
) )
213 output
.append( struct
.pack('>B', 0x00) )
215 output
.append( struct
.pack('>B', 0x80) )
217 return ''.join(output
)
220 if __name__
== '__main__':
221 username
= 'armooo@armooo.net'
222 password
= 'in(into)'
223 tsn
= '6520001802C0F2A'
224 url
= 'http://10.0.1.52:9032/Steph%27s%20Videos/Weekend%20%28Godard%201967%29.avi'
226 mind
= Mind(username
, password
, True)
227 mind
.pushVideo(tsn
, url
)