Check for new downloads every 15mins
[pyTivo.git] / plugins / webvideo / webvideo.py
blob4395dc93feb0b2ebd35499978f9ba996769bcd32
1 from plugins.video.video import Video, VideoDetails
2 import mind
3 import config
5 import xmpp
7 import threading
8 import urllib2
9 import os.path
10 import shutil
11 import os.path
12 import time
13 import os
14 import urlparse
15 import urllib
16 import xml.etree.ElementTree as ElementTree
17 import Queue
18 import logging
20 CLASS_NAME = 'WebVideo'
23 class WebVideo(Video):
25 CONTENT_TYPE = 'x-not-for/tivo'
27 def init(self):
28 self.__logger = logging.getLogger('pyTivo.webvideo')
29 self.work_queue = Queue.Queue()
30 self.download_thread_num = 1
31 self.in_progress = {}
32 self.in_progress_lock = threading.Lock()
34 self.startXMPP()
35 self.startWorkerThreads()
37 def startXMPP(self):
38 m = mind.getMind()
39 xmpp_info = m.getXMPPLoginInfo()
41 jid=xmpp.protocol.JID(xmpp_info['username'] + '/pyTivo')
42 cl=xmpp.Client(
43 server=xmpp_info['server'],
44 port=xmpp_info['port'],
45 debug=[],
47 self.__logger.debug('Connecting to %s:%s' % (xmpp_info['server'], xmpp_info['port']))
48 cl.connect()
49 cl.RegisterHandler('message', self.processMessage)
50 self.__logger.debug('Loging in as %s/pyTivo' % xmpp_info['username'])
51 cl.auth(user=jid.getNode(), password=config.getTivoPassword(), resource='pyTivo')
53 cl.sendInitPresence(requestRoster=0)
55 for user_name in xmpp_info['presence_list']:
56 self.__logger.debug('Sending presence to %s' % user_name)
57 jid=xmpp.protocol.JID(user_name)
58 cl.sendPresence(jid)
60 t = threading.Thread(target=self.processXMPP, args=(cl,))
61 t.setDaemon(True)
62 t.start()
64 def startWorkerThreads(self):
65 for i in range(self.download_thread_num):
66 t = threading.Thread(target=self.processDlRequest, name='webvideo downloader')
67 t.setDaemon(True)
68 t.start()
70 t = threading.Thread(target=self.watchQueue, name='webvideo queue watcher')
71 t.setDaemon(True)
72 t.start()
74 def processXMPP(self, client):
75 while client.Process(3):
76 pass
78 def processMessage(self, sess, mess):
79 self.__logger.debug('Got message\n %s' % mess.getBody())
80 xmpp_action = ElementTree.fromstring(mess.getBody())
82 method_name = 'xmpp_' + xmpp_action.findtext('action').lower()
83 if not hasattr(self, method_name):
84 return False
86 method = getattr(self, method_name)
87 method(xmpp_action)
89 def watchQueue(self):
90 while True:
91 self.xmpp_cdsupdate()
92 time.sleep(60*15)
94 def xmpp_cdsupdate(self, xml=None):
95 m = mind.getMind()
97 self.in_progress_lock.acquire()
98 try:
99 for request in m.getDownloadRequests():
100 if not request['bodyOfferId'] in self.in_progress:
101 self.__logger.debug('Adding request to queue, %s' % request)
102 self.in_progress[request['bodyOfferId']] = True
103 self.work_queue.put(request)
104 finally:
105 self.in_progress_lock.release()
107 def processDlRequest(self):
109 while True:
110 data = self.work_queue.get()
112 for share_name, settings in config.getShares():
113 if settings['type'] == 'webvideo':
114 break
115 self.__logger.debug('Processing request: %s' % data)
117 path = settings['path']
118 file_name = os.path.join(path, '%s-%s' % (data['bodyOfferId'] ,data['url'].split('/')[-1]))
120 self.downloadFile(data['url'], file_name)
122 tsn = data['bodyId']
123 file_info = VideoDetails()
124 file_info.update(self.metadata_full(file_name, tsn))
126 import socket
127 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
128 s.connect(('tivo.com',123))
129 ip = s.getsockname()[0]
130 port = config.getPort()
132 data['url'] = 'http://%s:%s' % (ip, port) + urllib.quote('/%s/%s' % (share_name, os.path.split(file_name)[-1]))
133 data['duration'] = file_info['duration'] / 1000
134 data['size'] = file_info['size']
136 self.__logger.debug('Complete request: %s' % data)
138 m = mind.getMind()
139 m.completeDownloadRequest(data)
141 self.in_progress_lock.acquire()
142 try:
143 del self.in_progress[data['bodyOfferId']]
144 finally:
145 self.in_progress_lock.release()
147 def downloadFile(self, url, file_path):
148 self.__logger.info('Downloading %s to %s' % (url, file_path))
150 outfile = open(file_path, 'awb')
151 size = os.path.getsize(file_path)
152 r = urllib2.Request(url)
153 if size:
154 r.add_header('Range', 'bytes=%s-' % size)
156 try:
157 infile = urllib2.urlopen(r)
158 except urllib2.HTTPError, e:
159 if not e.code == 416:
160 raise
161 infile = urllib2.urlopen(url)
162 if int(infile.info()['Content-Length']) == size:
163 self.__logger.debug('File was alraedy done. %s' % url)
164 return
165 else:
166 self.__logger.debug('File was not done byut could not resume. %s' % url)
167 outfile.close()
168 outfile = open(file_path, 'wb')
170 shutil.copyfileobj(infile, outfile, 8192)
172 self.__logger.info('Done downloading %s to %s' % (url, file_path))
174 def send_file(self, handler, container, name):
175 Video.send_file(self, handler, container, name)
177 o = urlparse.urlparse("http://fake.host" + handler.path)
178 path = urllib.unquote(o[2])
179 file_path = container['path'] + path[len(name) + 1:]
180 if os.path.exists(file_path):
181 self.__logger.info('Deleting file %s' % file_path)
182 os.unlink(file_path)