def infopage(self): self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl')) t.admin = '' for section, settings in config.getShares(): if 'type' in settings and settings['type'] == 'admin': t.admin += '<a href="/TiVoConnect?Command=Admin&Container=' + section\ + '">pyTivo Web Configuration</a><br>'\ + '<a href="/TiVoConnect?Command=NPL&Container=' + section\ + '">pyTivo ToGo</a><br>' if t.admin == '': t.admin = '<br><b>No Admin plugin installed in pyTivo.conf</b><br> If you wish to use'\ + ' the admin plugin add the following lines to pyTivo.conf<br><br>'\ + '[Admin]<br>type=admin' t.shares = 'Video shares:<br/>' for section, settings in config.getShares(): if settings.get('type') == 'video': t.shares += '<a href="TiVoConnect?Command=QueryContainer&Container=' + section\ + '">' + section + '</a><br/>' self.wfile.write(t) self.end_headers()
def setup(in_service=False): config.init(sys.argv[1:]) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger('pyTivo') logger.info('Last modified: ' + last_date()) logger.info('Python: ' + platform.python_version()) logger.info('System: ' + platform.platform()) for section, settings in config.getShares(): httpd.add_container(section, settings) b = beacon.Beacon() b.add_service('TiVoMediaServer:%s/http' % port) b.start() if 'listen' in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) httpd.set_service_status(in_service) logger.info('pyTivo is ready.') return httpd
def ToGo(self, handler, query): togo_path = config.get_server('togo_path') for name, data in config.getShares(): if togo_path == name: togo_path = data.get('path') if togo_path: tivoIP = query['TiVo'][0] tsn = config.tivos_by_ip(tivoIP) tivo_mak = config.get_tsn('tivo_mak', tsn) urls = query.get('Url', []) decode = 'decode' in query save = 'save' in query for theurl in urls: status[theurl] = {'running': False, 'error': '', 'rate': '', 'queued': True, 'size': 0, 'finished': False, 'decode': decode, 'save': save} if tivoIP in queue: queue[tivoIP].append(theurl) else: queue[tivoIP] = [theurl] thread.start_new_thread(ToGo.process_queue, (self, tivoIP, tivo_mak, togo_path)) logger.info('[%s] Queued "%s" for transfer to %s' % (time.strftime('%d/%b/%Y %H:%M:%S'), unquote(theurl), togo_path)) urlstring = '<br>'.join([unquote(x) for x in urls]) message = TRANS_QUEUE % (urlstring, togo_path) else: message = MISSING handler.redir(message, 5)
def SvcDoRun(self): config.init([]) config.init_logging() p = os.path.dirname(__file__) f = open(os.path.join(p, 'log.txt'), 'w') sys.stdout = f sys.stderr = f port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) for section, settings in config.getShares(): httpd.add_container(section, settings) b = beacon.Beacon() b.add_service('TiVoMediaServer:%s/http' % port) b.start() if 'listen' in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) while 1: sys.stdout.flush() (rx, tx, er) = select.select((httpd,), (), (), 5) for sck in rx: sck.handle_request() rc = win32event.WaitForSingleObject(self.stop_event, 5) if rc == win32event.WAIT_OBJECT_0: b.stop() break
def infopage(self): t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'), filter=EncodeUnicode) t.admin = '' if config.get_server('tivo_mak') and config.get_server('togo_path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&' + 'Container=' + quote(section) + '">Settings</a><br>') elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn and 'address' in config.tivos[tsn]: t.togo += ('<a href="/TiVoConnect?' + 'Command=NPL&Container=' + quote(section) + '&TiVo=' + config.tivos[tsn]['address'] + '">' + config.tivos[tsn]['name'] + '</a><br>') self.send_html(str(t))
def SvcDoRun(self): import sys, os p = os.path.dirname(__file__) f = open(os.path.join(p, 'log.txt'), 'w') sys.stdout = f sys.stderr = f port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) for section, settings in config.getShares(): httpd.add_container(section, settings) b = beacon.Beacon() b.add_service('TiVoMediaServer:' + str(port) + '/http') b.start() while 1: sys.stdout.flush() (rx, tx, er) = select.select((httpd, ), (), (), 5) for sck in rx: sck.handle_request() rc = win32event.WaitForSingleObject(self.stop_event, 5) if rc == win32event.WAIT_OBJECT_0: b.stop() break
def setup(in_service=False): config.init(sys.argv[1:], in_service) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger('pyTivo') logger.info('Last modified: ' + last_date()) logger.info('Python: ' + platform.python_version()) logger.info('System: ' + platform.platform()) for section, settings in config.getShares(): httpd.add_container(section, settings) b = beacon.Beacon() b.add_service('TiVoMediaServer:%s/http' % port) b.start() if 'listen' in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) httpd.set_service_status(in_service) logger.info('pyTivo is ready.') return httpd
def push_one_file(self, f): file_info = VideoDetails() file_info['valid'] = transcode.supported_format(f['path']) temp_share = config.get_server('temp_share', '') temp_share_path = '' if temp_share: for name, data in config.getShares(): if temp_share == name: temp_share_path = data.get('path') mime = 'video/mpeg' if config.isHDtivo(f['tsn']): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(f['path'], f['tsn'], m)[0]: mime = m break if (mime == 'video/mpeg' and transcode.mp4_remuxable(f['path'], f['tsn'])): new_path = transcode.mp4_remux(f['path'], f['name'], f['tsn'], temp_share_path) if new_path: mime = 'video/mp4' f['name'] = new_path if temp_share_path: ip = config.get_ip() port = config.getPort() container = quote(temp_share) + '/' f['url'] = 'http://%s:%s/%s' % (ip, port, container) if file_info['valid']: file_info.update(self.metadata_full(f['path'], f['tsn'], mime)) url = f['url'] + quote(f['name']) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(f['tsn']) m.pushVideo( tsn = f['tsn'], url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except Exception, msg: logger.error(msg)
def ToGo(self, handler, query): subcname = query['Container'][0] cname = subcname.split('/')[0] for name, data in config.getShares(): if cname == name: if 'tivo_mak' in data: tivo_mak = data['tivo_mak'] else: tivo_mak = "" if 'togo_path' in data: togo_path = data['togo_path'] else: togo_path = "" if tivo_mak != "" and togo_path != "": parse_url = urlparse(str(query['Url'][0])) theurl = 'http://' + parse_url[1].split( ':')[0] + parse_url[2] + "?" + parse_url[4] password = tivo_mak #TiVo MAK tivoIP = query['TiVo'][0] name = unquote(parse_url[2])[10:300].split('.') name.insert(-1, " - " + unquote(parse_url[4]).split("id=")[1] + ".") outfile = os.path.join(togo_path, "".join(name)) status[theurl] = { 'running': True, 'error': '', 'rate': '', 'finished': False } thread.start_new_thread(Admin.get_tivo_file, (self, theurl, password, tivoIP, outfile)) handler.send_response(200) handler.end_headers() t = Template( file=os.path.join(SCRIPTDIR, 'templates', 'redirect.tmpl')) t.container = cname t.time = '3' t.url = '/' + query['Redirect'][0] t.text = '<h3>Transfer Initiated.</h3> <br>You selected transfer has been initiated.'+\ '<br> The <a href="/'+ query['Redirect'][0] +'"> ToGo</a> page will reload in 3 seconds.' handler.wfile.write(t) else: handler.send_response(200) handler.end_headers() t = Template( file=os.path.join(SCRIPTDIR, 'templates', 'redirect.tmpl')) t.container = cname t.time = '10' t.url = '/' + query['Redirect'][0] t.text = '<h3>Missing Data.</h3> <br>You must set both "tivo_mak" and "togo_path" before using this function.'+\ '<br> The <a href="/'+ query['Redirect'][0] +'"> ToGo</a> page will reload in 10 seconds.' handler.wfile.write(t)
def root_container(self): tsn = self.headers.getheader('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = [] for section, settings in tsnshares: try: settings['content_type'] = \ GetPlugin(settings['type']).CONTENT_TYPE tsncontainers.append((section, settings)) except Exception, msg: self.server.logger.error(section + ' - ' + str(msg))
def root_container(self): tsn = self.headers.getheader('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = {} for section, settings in tsnshares: try: settings['content_type'] = \ GetPlugin(settings['type']).CONTENT_TYPE tsncontainers[section] = settings except Exception, msg: print section, '-', msg
def do_command(self, query, command, target, tsn): for name, container in config.getShares(tsn): if target == name: plugin = GetPlugin(container['type']) if hasattr(plugin, command): self.cname = name self.container = container method = getattr(plugin, command) method(self, query) return True else: break return False
def root_container(self): tsn = self.headers.getheader('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = [] for section, settings in tsnshares: try: mime = GetPlugin(settings['type']).CONTENT_TYPE if mime.split('/')[1] in ('tivo-videos', 'tivo-music', 'tivo-photos'): settings['content_type'] = mime tsncontainers.append((section, settings)) except Exception, msg: self.server.logger.error(section + ' - ' + str(msg))
def processDlRequest(self): while True: data = self.work_queue.get() for share_name, settings in config.getShares(): if settings['type'] == 'webvideo': break self.__logger.debug('Processing request: %s' % data) path = settings['path'] file_name = os.path.join(path, '%s-%s' % (data['bodyOfferId'].replace(':', '-'), data['url'].split('/')[-1])) status = self.downloadFile(data['url'], file_name) mime = 'video/mpeg' if status: tsn = data['bodyId'][4:] file_info = VideoDetails() if config.isHDtivo(tsn): for m in ['video/mp4', 'video/bif']: if tivo_compatible(file_name, tsn, m)[0]: mime = m break file_info.update(self.metadata_full(file_name, tsn, mime)) ip = config.get_ip() port = config.getPort() data['url'] = ('http://%s:%s' % (ip, port) + urllib.quote('/%s/%s' % (share_name, os.path.basename(file_name)))) data['duration'] = file_info['duration'] / 1000 data['size'] = file_info['size'] self.__logger.debug('Complete request: %s' % data) m = mind.getMind() m.completeDownloadRequest(data, status, mime) self.in_progress_lock.acquire() try: del self.in_progress[data['bodyOfferId']] finally: self.in_progress_lock.release()
def setup(in_service=False): config.init(sys.argv[1:]) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger('pyTivo') logger.info('Last modified: ' + last_date()) logger.info('Python: ' + platform.python_version()) logger.info('System: ' + platform.platform()) for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get('precache', 'False').lower() == 'true': plugin = GetPlugin(settings.get('type')) if hasattr(plugin, 'pre_cache'): logger.info('Pre-caching the ' + section + ' share.') pre_cache_filter = getattr(plugin, 'pre_cache') def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else: pre_cache_filter(f) except: pass build_recursive_list(settings.get('path')) b = beacon.Beacon() b.add_service('TiVoMediaServer:%s/http' % port) b.start() if 'listen' in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) httpd.set_service_status(in_service) logger.info('pyTivo is ready.') return httpd
def handle_query(self, query, tsn): mname = False if 'Command' in query and len(query['Command']) >= 1: command = query['Command'][0] # If we are looking at the root container if (command == 'QueryContainer' and (not 'Container' in query or query['Container'][0] == '/')): self.root_container() return if 'Container' in query: # Dispatch to the container plugin basepath = query['Container'][0].split('/')[0] for name, container in config.getShares(tsn): if basepath == name: plugin = GetPlugin(container['type']) if hasattr(plugin, command): method = getattr(plugin, command) method(self, query) return else: break elif (command == 'QueryFormats' and 'SourceFormat' in query and query['SourceFormat'][0].startswith('video')): self.send_response(200) self.send_header('Content-type', 'text/xml') self.end_headers() if config.hasTStivo(tsn): self.wfile.write(VIDEO_FORMATS_TS) else: self.wfile.write(VIDEO_FORMATS) return elif command == 'FlushServer': # Does nothing -- included for completeness self.send_response(200) self.end_headers() return # If we made it here it means we couldn't match the request to # anything. self.unsupported(query)
def ToGo(self, handler, query): subcname = query['Container'][0] cname = subcname.split('/')[0] for name, data in config.getShares(): if cname == name: if 'tivo_mak' in data: tivo_mak = data['tivo_mak'] else: tivo_mak = "" if 'togo_path' in data: togo_path = data['togo_path'] else: togo_path = "" if tivo_mak != "" and togo_path != "": parse_url = urlparse(str(query['Url'][0])) theurl = 'http://' + parse_url[1].split(':')[0] + parse_url[2] + "?" + parse_url[4] password = tivo_mak #TiVo MAK tivoIP = query['TiVo'][0] name = unquote(parse_url[2])[10:300].split('.') name.insert(-1," - " + unquote(parse_url[4]).split("id=")[1] + ".") outfile = os.path.join(togo_path, "".join(name)) status[theurl] = {'running':True, 'error':'', 'rate':'', 'finished':False} thread.start_new_thread(Admin.get_tivo_file, (self, theurl, password, tivoIP, outfile)) handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR,'templates', 'redirect.tmpl')) t.container = cname t.time = '3' t.url = '/'+ query['Redirect'][0] t.text = '<h3>Transfer Initiated.</h3> <br>You selected transfer has been initiated.'+\ '<br> The <a href="/'+ query['Redirect'][0] +'"> ToGo</a> page will reload in 3 seconds.' handler.wfile.write(t) else: handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR,'templates', 'redirect.tmpl')) t.container = cname t.time = '10' t.url = '/'+ query['Redirect'][0] t.text = '<h3>Missing Data.</h3> <br>You must set both "tivo_mak" and "togo_path" before using this function.'+\ '<br> The <a href="/'+ query['Redirect'][0] +'"> ToGo</a> page will reload in 10 seconds.' handler.wfile.write(t)
def infopage(self): useragent = self.headers.getheader('User-Agent', '') if useragent.lower().find('mobile') > 0: t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page_mob.tmpl'), filter=EncodeUnicode) else: t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'), filter=EncodeUnicode) t.admin = '' if config.get_server('tivo_mak') and config.get_server('togo_path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' if (config.get_server('tivo_username') and config.get_server('tivo_password')): t.shares = '<br>Push from video shares:<br>' else: t.shares = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&' + 'Container=' + quote(section) + '">Settings</a><br>') elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn: t.togo += ('<a href="/TiVoConnect?' + 'Command=NPL&Container=' + quote(section) + '&TiVo=' + config.tivos[tsn] + '">' + escape(config.tivo_names[tsn]) + '</a><br>') elif plugin_type and t.shares: plugin = GetPlugin(plugin_type) if hasattr(plugin, 'Push'): t.shares += ('<a href="/TiVoConnect?Command=' + 'QueryContainer&Container=' + quote(section) + '&Format=text/html">' + section + '</a><br>') self.send_html(str(t))
def setup(in_service=False): config.init(sys.argv[1:]) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(("", int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger("pyTivo") for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get("precache", "False").lower() == "true": plugin = GetPlugin(settings.get("type")) if hasattr(plugin, "pre_cache"): logger.info("Pre-caching the " + section + " share.") pre_cache_filter = getattr(plugin, "pre_cache") def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else: pre_cache_filter(f) except: pass build_recursive_list(settings.get("path")) b = beacon.Beacon() b.add_service("TiVoMediaServer:%s/http" % port) b.start() if "listen" in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) httpd.set_service_status(in_service) logger.info("pyTivo is ready.") return httpd
def ToGo(self, handler, query): togo_path = config.get_server('togo_path') for name, data in config.getShares(): if togo_path == name: togo_path = data.get('path') if togo_path: tivoIP = query['TiVo'][0] tsn = config.tivos_by_ip(tivoIP) tivo_mak = config.get_tsn('tivo_mak', tsn) urls = query.get('Url', []) decode = 'decode' in query save = 'save' in query ts_format = 'ts_format' in query for theurl in urls: status[theurl] = { 'running': False, 'error': '', 'rate': '', 'queued': True, 'size': 0, 'finished': False, 'decode': decode, 'save': save, 'ts_format': ts_format } if tivoIP in queue: queue[tivoIP].append(theurl) else: queue[tivoIP] = [theurl] thread.start_new_thread( ToGo.process_queue, (self, tivoIP, tivo_mak, togo_path)) logger.info('[%s] Queued "%s" for transfer to %s' % (time.strftime('%d/%b/%Y %H:%M:%S'), unquote(theurl), togo_path)) urlstring = '<br>'.join( [unicode(unquote(x), 'utf-8') for x in urls]) message = TRANS_QUEUE % (urlstring, togo_path) else: message = MISSING handler.redir(message, 5)
def infopage(self): self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'), filter=EncodeUnicode) t.admin = '' if config.get_server('tivo_mak') and config.get_server('togo_path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' if (config.get_server('tivo_username') and config.get_server('tivo_password')): t.shares = '<br>Push from video shares:<br>' else: t.shares = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&' + 'Container=' + quote(section) + '">Web Configuration</a><br>') elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn: t.togo += ('<a href="/TiVoConnect?' + 'Command=NPL&Container=' + quote(section) + '&TiVo=' + config.tivos[tsn] + '">' + escape(config.tivo_names[tsn]) + '</a><br>') elif plugin_type == 'video' and t.shares: t.shares += ('<a href="TiVoConnect?Command=' + 'QueryContainer&Container=' + quote(section) + '&Format=text/html">' + section + '</a><br>') self.wfile.write(t)
def infopage(self): t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'), filter=EncodeUnicode) t.admin = '' if config.get_server('tivo_mak') and config.get_server('togo_path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' if (config.get_server('tivo_username') and config.get_server('tivo_password')): t.shares = '<br>Push from video shares:<br>' else: t.shares = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&' + 'Container=' + quote(section) + '">Web Configuration</a><br>') elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn: t.togo += ('<a href="/TiVoConnect?' + 'Command=NPL&Container=' + quote(section) + '&TiVo=' + config.tivos[tsn] + '">' + escape(config.tivo_names[tsn]) + '</a><br>') elif plugin_type and t.shares: plugin = GetPlugin(plugin_type) if hasattr(plugin, 'Push'): t.shares += ('<a href="/TiVoConnect?Command=' + 'QueryContainer&Container=' + quote(section) + '&Format=text/html">' + section + '</a><br>') self.send_html(str(t))
def infopage(self): t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl')) t.version = PYTIVO_VERSION t.admin = '' if config.get_server('tivo_mak') and config.get_togo('path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&Container={}">Settings</a><br>' .format(quote(section))) elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn and 'address' in config.tivos[tsn]: t.togo += ('<a href="/TiVoConnect?Command=NPL&Container={}&TiVo={}">{}</a><br>' .format(quote(section), config.tivos[tsn]['address'], config.tivos[tsn]['name'])) self.send_html(str(t))
def root_container(self): tsn = self.headers.get('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = [] for section, settings in tsnshares: try: mime = GetPlugin(settings['type']).CONTENT_TYPE if mime.split('/')[1] in ('tivo-videos', 'tivo-music', 'tivo-photos'): settings['content_type'] = mime tsncontainers.append((section, settings)) except Exception as msg: self.server.logger.error('%s - %s', section, str(msg)) t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'root_container.tmpl')) if self.server.beacon.bd: t.renamed = self.server.beacon.bd.renamed else: t.renamed = {} t.containers = tsncontainers t.hostname = socket.gethostname() t.escape = escape t.quote = quote self.send_xml(str(t))
def reset(self): self.containers.clear() for section, settings in config.getShares(): self.add_container(section, settings)
def ToGo(handler, query): """ HTTP command handler to download a set of recordings from a Tivo. If there is already a thread downloading recordings from that Tivo, the new recordings will be appended to the existing download task list for that Tivo, otherwise a new task list will be created and a thread spawned to process it. """ togo_path = config.get_togo('path') for name, data in config.getShares(): if togo_path == name: togo_path = data.get('path') if togo_path: tivoIP = query['TiVo'][0] tsn = config.tivos_by_ip(tivoIP) tivo_name = config.tivos[tsn].get('name', tivoIP) tivo_mak = config.get_tsn('tivo_mak', tsn) urls = query.get('Url', []) decode = 'decode' in query save = 'save' in query ts_format = 'ts_format' in query and config.is_ts_capable(tsn) sortable = bool(config.get_togo('sortable_names', False)) for theurl in urls: status = {'url': theurl, 'running': False, 'queued': True, 'finished': False, 'showinfo': showinfo[theurl], # metadata information about the show 'decode': decode, # decode the downloaded tivo file 'save': save, # save the tivo file's metadata to a .txt file 'ts_format': ts_format, # download using transport stream otherwise program stream 'sortable': sortable, # name saved tivo file in a sortable manner 'error': '', 'rate': 0, 'size': 0, 'retry': 0, 'download_attempts': [], # information about each download attempt (used for sync error log) 'ts_error_packets': [], # list of TS packets w/ sync lost as tuples (packet_no, count) 'best_attempt_index': None, # index into download_attempts of the attempt w/ fewest errors 'best_file': '', 'best_error_count': None} # count of TS packets lost (sync byte was wrong) in 'best_file' with active_tivos_lock: if tivoIP in active_tivos: with active_tivos[tivoIP]['lock']: active_tivos[tivoIP]['queue'].append(status) else: # we have to add authentication info again because the # download netloc may be different from that used to # retrieve the list of recordings (and in fact the port # is different, 443 to get the NPL and 80 for downloading). auth_handler.add_password('TiVo DVR', urlsplit(theurl).netloc, 'tivo', tivo_mak) logger.debug('ToGo: add password for TiVo DVR netloc: %s', urlsplit(theurl).netloc) active_tivos[tivoIP] = {'tivoIP': tivoIP, 'lock': RLock(), 'thread': None, 'tivo_name': tivo_name, 'mak': tivo_mak, 'dest_path': togo_path, 'fn_format_info': {'episode': config.get_togo('episode_fn'), 'movie': config.get_togo('movie_fn') }, 'ts_error_mode': config.get_togo('ts_error_mode', 'ignore'), 'ts_max_retries': int(config.get_togo('ts_max_retries', 0)), 'queue': [status]} active_tivos[tivoIP]['thread'] = TivoDownload(tivoIP, active_tivos, active_tivos_lock, tivo_open) active_tivos[tivoIP]['thread'].start() logger.info('[%s] Queued "%s" for transfer to %s', time.strftime('%d/%b/%Y %H:%M:%S'), unquote(theurl), togo_path) urlstring = '<br>'.join([unquote(x) for x in urls]) message = TRANS_QUEUE % (urlstring, togo_path) else: message = MISSING handler.redir(message, 5)
#!/usr/bin/env python import beacon, httpserver, os, sys import config from plugin import GetPlugin port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get('precache', 'False').lower() == 'true': plugin = GetPlugin(settings.get('type')) if hasattr(plugin, 'pre_cache'): print 'Pre-caching the', section, 'share.' pre_cache_filter = getattr(plugin, 'pre_cache') def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else: pre_cache_filter(f) except: pass build_recursive_list(settings.get('path'))
def push_one_file(self, f): file_info = VideoDetails() file_info['valid'] = transcode.supported_format(f['path']) temp_share = config.get_server('temp_share', '') temp_share_path = '' remux_path = os.path.dirname(f['path']) if temp_share: for name, data in config.getShares(): if temp_share == name: temp_share_path = data.get('path') remux_path = temp_share_path mime = 'video/mpeg' if config.isHDtivo(f['tsn']): for m in ['video/mp4', 'video/bif']: if transcode.tivo_compatible(f['path'], f['tsn'], m)[0]: mime = m break if (mime == 'video/mpeg' and transcode.mp4_remuxable(f['path'], f['tsn'])): if config.get_freeSpace(remux_path, f['path']): new_path = transcode.mp4_remux(f['path'], f['name'], f['tsn'], temp_share_path) if new_path: mime = 'video/mp4' f['name'] = new_path if temp_share_path: ip = config.get_ip() port = config.getPort() container = quote(temp_share) + '/' f['url'] = 'http://%s:%s/%s' % (ip, port, container) else: logger.warning('Not enough disk space to perform remux, ' + 'transcoding instead.') if file_info['valid']: file_info.update(self.metadata_full(f['path'], f['tsn'], mime)) url = f['url'] + quote(f['name']) title = file_info['seriesTitle'] if not title: title = file_info['title'] source = file_info['seriesId'] if not source: source = title subtitle = file_info['episodeTitle'] try: m = mind.getMind(f['tsn']) m.pushVideo( tsn = f['tsn'], url = url, description = file_info['description'], duration = file_info['duration'] / 1000, size = file_info['size'], title = title, subtitle = subtitle, source = source, mime = mime, tvrating = file_info['tvRating']) except ValueError, msg: if 'usernamePasswordError' in msg: if f['name'].endswith('.pyTivo-temp'): fname = os.path.join(remux_path, os.path.basename(f['name'])) fname = unicode(fname, 'utf-8') os.remove(fname) logger.debug(fname + ' has been removed')
def exceptionLogger(*args): sys.excepthook = sys.__excepthook__ logging.getLogger('pyTivo').error('Exception in pyTivo', exc_info=args) config.init(sys.argv[1:]) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger('pyTivo') for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get('precache', 'False').lower() == 'true': plugin = GetPlugin(settings.get('type')) if hasattr(plugin, 'pre_cache'): logger.info('Pre-caching the ' + section + ' share.') pre_cache_filter = getattr(plugin, 'pre_cache') def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else:
def NPL(self, handler, query): shows_per_page = 50 #Change this to alter the number of shows returned per page subcname = query['Container'][0] cname = subcname.split('/')[0] folder = '' AnchorItem = '' AnchorOffset= '' for name, data in config.getShares(): if cname == name: if 'tivo_mak' in data: tivo_mak = data['tivo_mak'] else: tivo_mak = "" if 'togo_path' in data: togo_path = data['togo_path'] else: togo_path = "" if 'TiVo' in query: tivoIP = query['TiVo'][0] theurl = 'https://'+ tivoIP +'/TiVoConnect?Command=QueryContainer&ItemCount='+ str(shows_per_page) +'&Container=/NowPlaying' if 'Folder' in query: folder += str(query['Folder'][0]) theurl += '/' + folder if 'AnchorItem' in query: AnchorItem += str(query['AnchorItem'][0]) theurl += '&AnchorItem=' + quote(AnchorItem) if 'AnchorOffset' in query: AnchorOffset += str(query['AnchorOffset'][0]) theurl += '&AnchorOffset=' + AnchorOffset password = tivo_mak #TiVo MAK r=urllib2.Request(theurl) auth_handler = urllib2.HTTPDigestAuthHandler() auth_handler.add_password('TiVo DVR', tivoIP, 'tivo', password) opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener) if theurl in tivo_cache: #check to see if we have accessed this page before if tivo_cache[theurl]['thepage'] == '' or (time.time() - tivo_cache[theurl]['thepage_time']) >= 60: #if page is empty or old then retreive it try: handle = urllib2.urlopen(r) except IOError, e: handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR,'templates', 'redirect.tmpl')) t.container = cname t.time = '20' t.url = '/TiVoConnect?Command=NPL&Container=' + cname t.text = '<h3>Unable to Connect to TiVo.</h3> <br>pyTivo was unable to connect to the TiVo at ' + tivoIP +\ '<br>This most likely caused by an incorrect Media Access Key. Please return to the ToGo page and double check your Media Access Key.' +\ '<br> The <a href="/TiVoConnect?Command=NPL&Container='+ cname + '"> ToGo</a> page will reload in 20 seconds.' handler.wfile.write(t) return tivo_cache[theurl]['thepage'] = handle.read() tivo_cache[theurl]['thepage_time'] = time.time() else: #not in cache try: handle = urllib2.urlopen(r) except IOError, e: handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR,'templates', 'redirect.tmpl')) t.container = cname t.time = '20' t.url = '/TiVoConnect?Command=NPL&Container=' + cname t.text = '<h3>Unable to Connect to TiVo.</h3> <br>pyTivo was unable to connect to the TiVo at ' + tivoIP +\ '<br>This most likely caused by an incorrect Media Access Key. Please return to the ToGo page and double check your Media Access Key.' +\ '<br> The <a href="/TiVoConnect?Command=NPL&Container='+ cname + '"> ToGo</a> page will reload in 20 seconds.' handler.wfile.write(t) return tivo_cache[theurl] = {} tivo_cache[theurl]['thepage'] = handle.read() tivo_cache[theurl]['thepage_time'] = time.time()
def ToGo(self, handler, query): togo_path = config.get_server('togo_path') for name, data in config.getShares(): if togo_path == name: togo_path = data.get('path') if togo_path: tivoIP = query['TiVo'][0] tsn = config.tivos_by_ip(tivoIP) tivo_mak = config.get_tsn('tivo_mak', tsn) urls = query.get('Url', []) decode = 'decode' in query save = 'save' in query if 'postprocess' in query: postprocess = query['postprocess'][0] else: postprocess = config.get_server('vrd_post_processing') if 'postprocess_profile' in query: postprocess_profile = query['postprocess_profile'][0] else: postprocess_profile = config.get_server('vrd_profile', '') postprocess_decrypt = 'postprocess_decrypt' in query if not postprocess_decrypt: try: postprocess_decrypt = config.config.getboolean( 'Server', 'vrd_decrypt_qsf') except: postprocess_decrypt = False postprocess_delete = 'postprocess_delete' in query if not postprocess_delete: try: postprocess_delete = config.config.getboolean( 'Server', 'vrd_delete_on_success') except: postprocess_delete = False ts_format = 'ts_format' in query and config.is_ts_capable(tsn) for theurl in urls: if theurl in status: del status[theurl] status[theurl] = { 'running': False, 'status': '', 'error': '', 'rate': 0, 'percent': 0, 'queued': True, 'size': 0, 'postprocessing': False, 'finished': False, 'decode': decode, 'save': save, 'ts_format': ts_format, 'postprocess': postprocess, 'postprocess_profile': postprocess_profile, 'postprocess_decrypt': postprocess_decrypt, 'postprocess_delete': postprocess_delete, 'retry': 0, 'ts_max_retries': int(config.get_server('togo_ts_max_retries', 0)), 'ts_error_count': 0, 'best_file': '', 'best_error_count': 0 } if tivoIP in queue: queue[tivoIP].append(theurl) else: queue[tivoIP] = [theurl] thread.start_new_thread( ToGo.process_queue, (self, tivoIP, tivo_mak, togo_path)) logger.info('[%s] Queued "%s" for transfer to %s' % (time.strftime('%d/%b/%Y %H:%M:%S'), unquote(theurl), togo_path)) urlstring = '<br>'.join( [unicode(unquote(x), 'utf-8') for x in urls]) message = TRANS_QUEUE % (urlstring, togo_path) else: message = MISSING handler.redir(message, 5)
def NPL(self, handler, query): shows_per_page = 50 #Change this to alter the number of shows returned per page subcname = query['Container'][0] cname = subcname.split('/')[0] folder = '' AnchorItem = '' AnchorOffset = '' for name, data in config.getShares(): if cname == name: if 'tivo_mak' in data: tivo_mak = data['tivo_mak'] else: tivo_mak = "" if 'togo_path' in data: togo_path = data['togo_path'] else: togo_path = "" if 'TiVo' in query: tivoIP = query['TiVo'][0] theurl = 'https://' + tivoIP + '/TiVoConnect?Command=QueryContainer&ItemCount=' + str( shows_per_page) + '&Container=/NowPlaying' if 'Folder' in query: folder += str(query['Folder'][0]) theurl += '/' + folder if 'AnchorItem' in query: AnchorItem += str(query['AnchorItem'][0]) theurl += '&AnchorItem=' + quote(AnchorItem) if 'AnchorOffset' in query: AnchorOffset += str(query['AnchorOffset'][0]) theurl += '&AnchorOffset=' + AnchorOffset password = tivo_mak #TiVo MAK r = urllib2.Request(theurl) auth_handler = urllib2.HTTPDigestAuthHandler() auth_handler.add_password('TiVo DVR', tivoIP, 'tivo', password) opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener) if theurl in tivo_cache: #check to see if we have accessed this page before if tivo_cache[theurl]['thepage'] == '' or ( time.time() - tivo_cache[theurl]['thepage_time'] ) >= 60: #if page is empty or old then retreive it try: handle = urllib2.urlopen(r) except IOError, e: handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'redirect.tmpl')) t.container = cname t.time = '20' t.url = '/TiVoConnect?Command=NPL&Container=' + cname t.text = '<h3>Unable to Connect to TiVo.</h3> <br>pyTivo was unable to connect to the TiVo at ' + tivoIP +\ '<br>This most likely caused by an incorrect Media Access Key. Please return to the ToGo page and double check your Media Access Key.' +\ '<br> The <a href="/TiVoConnect?Command=NPL&Container='+ cname + '"> ToGo</a> page will reload in 20 seconds.' handler.wfile.write(t) return tivo_cache[theurl]['thepage'] = handle.read() tivo_cache[theurl]['thepage_time'] = time.time() else: #not in cache try: handle = urllib2.urlopen(r) except IOError, e: handler.send_response(200) handler.end_headers() t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'redirect.tmpl')) t.container = cname t.time = '20' t.url = '/TiVoConnect?Command=NPL&Container=' + cname t.text = '<h3>Unable to Connect to TiVo.</h3> <br>pyTivo was unable to connect to the TiVo at ' + tivoIP +\ '<br>This most likely caused by an incorrect Media Access Key. Please return to the ToGo page and double check your Media Access Key.' +\ '<br> The <a href="/TiVoConnect?Command=NPL&Container='+ cname + '"> ToGo</a> page will reload in 20 seconds.' handler.wfile.write(t) return tivo_cache[theurl] = {} tivo_cache[theurl]['thepage'] = handle.read() tivo_cache[theurl]['thepage_time'] = time.time()