def get_rutor_playlist(category, sort, text, spr, parent_page): items_per_page = config.items_per_page items = [] page = 0 while len(items) < items_per_page * int(parent_page): rutor_list = SearchN(category, sort, text, spr, str(page), min_size=config.min_size, max_size=config.max_size, min_peers=config.min_peers, max_peers=config.max_peers) page += 1 items += rutor_list print "len(items)=%s" % len(items) print "(items_per_page * int(parent_page) - items_per_page)=%s" % (items_per_page * int(parent_page) - items_per_page) print "items_per_page * int(parent_page)=%s" % (items_per_page * int(parent_page)) playlist = PlaylistGenerator() for d in items[(items_per_page * int(parent_page) - items_per_page):items_per_page * int(parent_page)]: playlist.addItem(d) Title = u"[НАЙТИ ЕЩЕ]" itemdict = {'title': Title, 'url': '/rutor/category/%s/?page=%s' % (category, int(page) + 1), 'description_title': Title, 'description': '', 'type': 'channel' } playlist.addItem(itemdict) return playlist
def handle(self, connection): hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() if not self.downloadPlaylist(config.url): connection.dieWithError() return # Un-JSON channel list try: jsonplaylist = json.loads(Superpomoyka.playlist) except Exception as e: Superpomoyka.logger.error("Can't load JSON! " + repr(e)) return try: channels = jsonplaylist['channels'] Superpomoyka.logger.info('%d channels found' % len(channels)) except Exception as e: Superpomoyka.logger.error("Can't parse JSON! " + repr(e)) return playlistgen = PlaylistGenerator() for channel in channels: playlistgen.addItem(channel) exported = playlistgen.exportm3u(hostport, add_ts=False) exported = exported.encode('utf-8') connection.wfile.write(exported)
def handle(self, connection): # 30 minutes cache if not Torrenttv.playlist or (int(time.time()) - Torrenttv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Match playlist with regexp matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', Torrenttv.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for match in matches: playlistgen.addItem(match.groupdict()) connection.wfile.write(playlistgen.exportm3u(hostport, add_ts))
def handle(self, connection): # 30 minutes cache if not Torrenttv.playlist or (int(time.time()) - Torrenttv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Match playlist with regexp matches = re.finditer(r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', Torrenttv.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for match in matches: playlistgen.addItem(match.groupdict()) connection.wfile.write(playlistgen.exportm3u(hostport, add_ts))
def handle(self, connection): if config.plttl != 0 and (not Torrenttv.playlist or (int(time.time()) - Torrenttv.playlisttime > config.plttl * 60)): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Match playlist with regexp matches = re.finditer(r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', Torrenttv.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for match in matches: itemdict = match.groupdict() name = itemdict.get('name').decode('UTF-8') logo = config.logomap.get(name) if logo is not None: itemdict['logo'] = logo playlistgen.addItem(itemdict) header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' %(config.tvgurl, config.tvgshift) connection.wfile.write(playlistgen.exportm3u(hostport, add_ts=add_ts, header=header))
def downloadPlaylist(self): try: self.logger.debug('Trying to download playlist') req = urllib2.Request(config.url, headers={'User-Agent': "Magic Browser"}) origin = urllib2.urlopen(req, timeout=10).read() matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = config.logomap.get(name) url = itemdict['url'] self.playlist.addItem(itemdict) if logo: itemdict['logo'] = logo if (url.startswith('acestream://')) or ( url.startswith('http://') and url.endswith('.acelive')): self.channels[name] = url itemdict['url'] = urllib2.quote(encname, '') + '.mp4' m.update(encname) self.etag = '"' + m.hexdigest() + '"' except: self.logger.error("Can't download playlist!") self.logger.error(traceback.format_exc()) return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") except: # p2pproxy plugin seems not configured self.updatelogos = False return True
def handle(self, connection): hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) url = None list_type = self.getparam('type') if not list_type or list_type.startswith('ttv'): url = config.url_ttv elif list_type.startswith('mob_ttv'): url = config.url_mob_ttv elif list_type.startswith('allfon'): url = config.url_allfon if not self.downloadPlaylist(url): connection.dieWithError() return # Un-JSON channel list try: jsonplaylist = json.loads(Torrenttelik.playlist) except Exception as e: Torrenttelik.logger.error("Can't load JSON! " + repr(e)) return try: channels = jsonplaylist['channels'] except Exception as e: Torrenttelik.logger.error("Can't parse JSON! " + repr(e)) return add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for channel in channels: playlistgen.addItem(channel) exported = playlistgen.exportm3u(hostport, add_ts=add_ts) exported = exported.encode('utf-8') connection.wfile.write(exported)
def handle(self, connection, headers_only=False): hostport = connection.headers['Host'] if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Connection', 'close') connection.end_headers() return # 15 minutes cache if not Allfon.playlist or (int(time.time()) - Allfon.playlisttime > 15 * 60): if not self.downloadPlaylist(): connection.dieWithError() return matches = re.finditer( r'\#EXTINF\:0\,(?P<name>\S.+)\n.+\n.+\n(?P<url>^acestream.+$)', Allfon.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator( m3uchanneltemplate=config.m3uchanneltemplate) for match in matches: playlistgen.addItem(match.groupdict()) Allfon.logger.info('AllFon playlist created') url = urlparse.urlparse(connection.path) params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None header = '#EXTM3U url-tvg="%s" tvg-shift=%d deinterlace=1 m3uautoload=1 cache=1000\n' % ( config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u(hostport, header=header, add_ts=add_ts, fmt=fmt) connection.send_response(200) connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8') connection.send_header('Content-Length', str(len(exported))) connection.send_header('Connection', 'close') connection.end_headers() connection.wfile.write(exported)
def handle(self, connection): # 30 minutes cache if not Ytv.playlist or (int(time.time()) - Ytv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Un-JSON channel list try: jsonplaylist = json.loads(Ytv.playlist) except Exception as e: Ytv.logger.error("Can't load JSON! " + repr(e)) return False try: groups = dict( map(lambda item: item.values(), jsonplaylist['genres'])) channels = jsonplaylist['channels'] except Exception as e: Ytv.logger.error("Can't parse JSON! " + repr(e)) return False add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for channel in channels: groupid = channel.get('genre_id') if groupid and groups.get(groupid): channel['group'] = groups.get(groupid) playlistgen.addItem(channel) exported = playlistgen.exportm3u(hostport, add_ts) exported = exported.encode('utf-8') connection.wfile.write(exported)
def handle(self, connection, headers_only=False): # 30 minutes cache if not Allfon.playlist or (int(time.time()) - Allfon.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() if headers_only: return # Match playlist with regexp matches = re.finditer( r'\#EXTINF\:0\,(?P<name>\S.+)\n.+\n.+\n(?P<url>^acestream.+$)', Allfon.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator( m3uchanneltemplate=config.m3uchanneltemplate) for match in matches: playlistgen.addItem(match.groupdict()) url = urlparse.urlparse(connection.path) params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) connection.wfile.write( playlistgen.exportm3u(hostport, header=header, add_ts=add_ts, fmt=fmt))
def handle(self, connection): # 30 minutes cache if not Ytv.playlist or (int(time.time()) - Ytv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Un-JSON channel list try: jsonplaylist = json.loads(Ytv.playlist) except Exception as e: Ytv.logger.error("Can't load JSON! " + repr(e)) return False try: groups = dict(map(lambda item: item.values(), jsonplaylist['genres'])) channels = jsonplaylist['channels'] except Exception as e: Ytv.logger.error("Can't parse JSON! " + repr(e)) return False add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for channel in channels: groupid = channel.get('genre_id') if groupid and groups.get(groupid): channel['group'] = groups.get(groupid) playlistgen.addItem(channel) exported = playlistgen.exportm3u(hostport, add_ts) exported = exported.encode('utf-8') connection.wfile.write(exported)
def downloadPlaylist(self): try: self.logger.debug('Trying to download playlist') req = urllib2.Request(config.url, headers={'User-Agent' : "Magic Browser"}) origin = urllib2.urlopen(req, timeout=10).read() matches = re.finditer(r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = config.logomap.get(name) url = itemdict['url'] self.playlist.addItem(itemdict) if logo: itemdict['logo'] = logo if (url.startswith('acestream://')) or (url.startswith('http://') and url.endswith('.acelive')): self.channels[name] = url itemdict['url'] = urllib2.quote(encname, '') + '.mp4' m.update(encname) self.etag = '"' + m.hexdigest() + '"' except: self.logger.error("Can't download playlist!") self.logger.error(traceback.format_exc()) return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") except: # p2pproxy plugin seems not configured self.updatelogos = False return True
def handle(self, connection): # 30 minutes cache if not Torrenttv.playlist or (int(time.time()) - Torrenttv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Match playlist with regexp matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', Torrenttv.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for match in matches: itemdict = match.groupdict() name = itemdict.get('name').decode('UTF-8') logo = config.logomap.get(name) if logo is not None: itemdict['logo'] = logo playlistgen.addItem(itemdict) header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) connection.wfile.write( playlistgen.exportm3u(hostport, add_ts=add_ts, header=header))
def handle(self, connection, headers_only=False): # 30 minutes cache if not Allfon.playlist or (int(time.time()) - Allfon.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() if headers_only: return; # Match playlist with regexp matches = re.finditer(r'\#EXTINF\:0\,ALLFON\.ORG (?P<name>\S.+)\n.+\n.+\n(?P<url>^acestream.+$)', Allfon.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate) for match in matches: playlistgen.addItem(match.groupdict()) url = urlparse.urlparse(connection.path) params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' %(config.tvgurl, config.tvgshift) connection.wfile.write(playlistgen.exportm3u(hostport, header=header, add_ts=add_ts, fmt=fmt))
def handle(self, connection): # 30 minutes cache if not Playlist.playlist_json or (int(time.time()) - Playlist.playlisttime > 5 * 60): if not self.generatePlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] Playlist.logger.debug(connection.headers) connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Disposition', 'inline; filename="playlist.m3u"') connection.end_headers() # Un-JSON channel list try: jsonplaylist = json.loads(Playlist.playlist_json) except Exception as e: Playlist.logger.error("Can't parse JSON Radio Playlist!" + repr(e)) return False playlistgen = PlaylistGenerator() # Addind Radio channels from JSO for channel in jsonplaylist['radio']['channels']: channel['radio'] = 'true' channel['transit'] = False if not channel.get('hide'): playlistgen.addItem(channel) # Addind TV channels from JSON for channel in jsonplaylist['tv']['channels']: if not channel.get('hide'): playlistgen.addItem(channel) connection.wfile.write(playlistgen.exportm3u(hostport, False, Playlist.m3uheader % hostport).encode('utf-8'))
def get_rutor_playlist(category, sort, text, spr, parent_page): items_per_page = config.items_per_page items = [] page = 0 while len(items) < items_per_page * int(parent_page): rutor_list = SearchN(category, sort, text, spr, str(page), min_size=config.min_size, max_size=config.max_size, min_peers=config.min_peers, max_peers=config.max_peers) page += 1 items += rutor_list print "len(items)=%s" % len(items) print "(items_per_page * int(parent_page) - items_per_page)=%s" % ( items_per_page * int(parent_page) - items_per_page) print "items_per_page * int(parent_page)=%s" % (items_per_page * int(parent_page)) playlist = PlaylistGenerator() for d in items[(items_per_page * int(parent_page) - items_per_page):items_per_page * int(parent_page)]: playlist.addItem(d) Title = u"[НАЙТИ ЕЩЕ]" itemdict = { 'title': Title, 'url': '/rutor/category/%s/?page=%s' % (category, int(page) + 1), 'description_title': Title, 'description': '', 'type': 'channel' } playlist.addItem(itemdict) return playlist
def handle(self, connection, headers_only=False): query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) self.logger.debug('connection.reqtype=%s' % connection.reqtype) self.logger.debug(len(connection.splittedpath)) self.logger.debug('connection.splittedpath=%s' % connection.splittedpath) self.logger.debug('params=%s' % self.params) if connection.reqtype == 'rutor': if len(connection.splittedpath) < 2: connection.send_response(404) connection.send_header('Connection', 'close') connection.end_headers() return if len(connection.splittedpath) in (2, 3): # View Categories playlist = PlaylistGenerator() for cat in config.categories: Title = "[%s]" % cat[1] itemdict = {'title': Title, 'url': '/rutor/category/%s/' % cat[0], 'description_title': Title, 'description': '', 'type': 'channel' } playlist.addItem(itemdict) self.send_playlist(connection, playlist) if len(connection.splittedpath) == 5: if connection.splittedpath[2] == 'category': category = connection.splittedpath[3] self.logger.debug('Get category: %s' % category) # category = '1' sort = '0' text = '0' try: page = self.params['page'][0] except: page = '1' try: sort = self.params['sort'][0] except: sort = '0' spr = ["", "", "", "", "", ""] playlist = get_rutor_playlist(category, sort, text, spr, page) self.send_playlist(connection, playlist) if connection.splittedpath[2] == 'list': playlist = PlaylistGenerator() torrent_url = connection.splittedpath[3] torrent_url_unquoted = urllib2.unquote(connection.splittedpath[3]) self.logger.debug('list: "%s"' % torrent_url_unquoted) contentinfo = None with self.AceStuff.clientcounter.lock: if not self.AceStuff.clientcounter.idleace: self.AceStuff.clientcounter.idleace = self.AceStuff.clientcounter.createAce() contentinfo = self.AceStuff.clientcounter.idleace.GETCONTENTINFO('TORRENT', torrent_url_unquoted) if contentinfo and contentinfo.get('status') in (1, 2) and contentinfo.get('files'): files = contentinfo.get('files') files.sort() for filename, fid in files: Title = "[%s]" % filename itemdict = {'title': Title, 'url': '/playtorrent/%s/%s/%s.avi' % (torrent_url, fid, filename), 'description_title': Title, 'description': '', 'type': 'stream' } playlist.addItem(itemdict) else: Title = "[Not found files for play]" itemdict = {'title': Title, 'url': '/rutor/list/%s/' % torrent_url, 'description_title': Title, 'description': '', 'type': 'channel', } playlist.addItem(itemdict) hostport = connection.headers['Host'] exported = playlist.exportxml(hostport) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/xml') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported)
def handle(self, connection, headers_only=False): hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() if headers_only: return query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) url = None list_type = self.getparam('type') if not list_type or list_type.startswith('ttv'): url = config.url_ttv elif list_type.startswith('mob_ttv'): url = config.url_mob_ttv elif list_type.startswith('allfon'): url = config.url_allfon if not self.downloadPlaylist(url): connection.dieWithError() return # Un-JSON channel list try: jsonplaylist = json.loads(Torrenttelik.playlist) except Exception as e: Torrenttelik.logger.error("Can't load JSON! " + repr(e)) return try: channels = jsonplaylist['channels'] except Exception as e: Torrenttelik.logger.error("Can't parse JSON! " + repr(e)) return add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for channel in channels: channel['group'] = channel.get('cat', '') playlistgen.addItem(channel) Torrenttelik.logger.debug('Exporting') header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u(hostport, header=header, add_ts=add_ts, fmt=self.getparam('fmt')) exported = exported.encode('utf-8') connection.wfile.write(exported)
class Torrenttv(AceProxyPlugin): # ttvplaylist handler is obsolete handlers = ('torrenttv', 'ttvplaylist') def __init__(self, AceConfig, AceStuff): self.logger = logging.getLogger('plugin_torrenttv') self.lock = threading.Lock() self.channels = None self.playlist = None self.playlisttime = None self.etag = None self.logomap = config.logomap self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe' if config.updateevery: gevent.spawn(self.playlistTimedDownloader) def playlistTimedDownloader(self): while True: with self.lock: self.downloadPlaylist() gevent.sleep(config.updateevery * 60) def downloadPlaylist(self): try: self.logger.debug('Trying to download playlist') req = urllib2.Request(config.url, headers={'User-Agent' : "Magic Browser"}) origin = urllib2.urlopen(req, timeout=10).read() matches = re.finditer(r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = config.logomap.get(name) url = itemdict['url'] self.playlist.addItem(itemdict) if logo: itemdict['logo'] = logo if (url.startswith('acestream://')) or (url.startswith('http://') and url.endswith('.acelive')): self.channels[name] = url itemdict['url'] = urllib2.quote(encname, '') + '.mp4' m.update(encname) self.etag = '"' + m.hexdigest() + '"' except: self.logger.error("Can't download playlist!") self.logger.error(traceback.format_exc()) return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") except: # p2pproxy plugin seems not configured self.updatelogos = False return True def handle(self, connection, headers_only=False): play = False with self.lock: # 30 minutes cache if not self.playlist or (int(time.time()) - self.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return url = urlparse.urlparse(connection.path) params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None if url.path.startswith('/torrenttv/channel/'): if not url.path.endswith('.mp4'): connection.dieWithError() return name = urllib2.unquote(url.path[19:-4]).decode('UTF8') url = self.channels[name] if url.startswith('acestream://'): connection.path = '/pid/' + url[12:] + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'pid' else: connection.path = '/torrent/' + urllib2.quote(url, '') + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'torrent' play = True elif self.etag == connection.headers.get('If-None-Match'): self.logger.debug('ETag matches - returning 304') connection.send_response(304) connection.send_header('Connection', 'close') connection.end_headers() return else: hostport = connection.headers['Host'] path = '' if len(self.channels) == 0 else '/torrenttv/channel' add_ts = True if url.path.endswith('/ts') else False header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) exported = self.playlist.exportm3u(hostport, path, add_ts=add_ts, header=header, fmt=fmt) connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('ETag', self.etag) connection.send_header('Content-Length', str(len(exported))) connection.send_header('Connection', 'close') connection.end_headers() if play: connection.handleRequest(headers_only, name, config.logomap.get(name)) elif not headers_only: connection.wfile.write(exported)
class Torrenttv(AceProxyPlugin): # ttvplaylist handler is obsolete handlers = ('torrenttv', 'ttvplaylist') def __init__(self, AceConfig, AceStuff): self.logger = logging.getLogger('plugin_torrenttv') self.lock = threading.Lock() self.channels = None self.playlist = None self.playlisttime = None self.etag = None self.logomap = config.logomap self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe' if config.updateevery: gevent.spawn(self.playlistTimedDownloader) def playlistTimedDownloader(self): while True: with self.lock: self.downloadPlaylist() gevent.sleep(config.updateevery * 60) def downloadPlaylist(self): try: self.logger.debug('Trying to download playlist') req = urllib2.Request(config.url, headers={'User-Agent': "Magic Browser"}) origin = urllib2.urlopen(req, timeout=10).read() matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = config.logomap.get(name) url = itemdict['url'] self.playlist.addItem(itemdict) if logo: itemdict['logo'] = logo if (url.startswith('acestream://')) or ( url.startswith('http://') and url.endswith('.acelive')): self.channels[name] = url itemdict['url'] = urllib2.quote(encname, '') + '.mp4' m.update(encname) self.etag = '"' + m.hexdigest() + '"' except: self.logger.error("Can't download playlist!") self.logger.error(traceback.format_exc()) return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") except: # p2pproxy plugin seems not configured self.updatelogos = False return True def handle(self, connection, headers_only=False): play = False with self.lock: # 30 minutes cache if not self.playlist or (int(time.time()) - self.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return url = urlparse.urlparse(connection.path) params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None if url.path.startswith('/torrenttv/channel/'): if not url.path.endswith('.mp4'): connection.dieWithError() return name = urllib2.unquote(url.path[19:-4]).decode('UTF8') url = self.channels[name] if url.startswith('acestream://'): connection.path = '/pid/' + url[12:] + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'pid' else: connection.path = '/torrent/' + urllib2.quote( url, '') + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'torrent' play = True elif self.etag == connection.headers.get('If-None-Match'): self.logger.debug('ETag matches - returning 304') connection.send_response(304) connection.send_header('Connection', 'close') connection.end_headers() return else: hostport = connection.headers['Host'] path = '' if len(self.channels) == 0 else '/torrenttv/channel' add_ts = True if url.path.endswith('/ts') else False header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % ( config.tvgurl, config.tvgshift) exported = self.playlist.exportm3u(hostport, path, add_ts=add_ts, header=header, fmt=fmt) connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('ETag', self.etag) connection.send_header('Content-Length', str(len(exported))) connection.send_header('Connection', 'close') connection.end_headers() if play: connection.handleRequest(headers_only, name, config.logomap.get(name)) elif not headers_only: connection.wfile.write(exported)
def downloadPlaylist(self): try: self.logger.debug('Trying to download playlist') req = urllib2.Request(config.url, headers={'User-Agent': "Magic Browser"}) req.add_header('Accept-encoding', 'gzip') response = urllib2.urlopen(req, timeout=15) origin = '' if response.info().get('Content-Encoding') == 'gzip': # read the encoded response into a buffer buffer = StringIO(response.read()) # gzip decode the response f = gzip.GzipFile(fileobj=buffer) # store the result origin = f.read() # close the buffer buffer.close() # else if the response isn't gzip-encoded self.logger.debug('Playlist downloaded using gzip compression') else: # store the result origin = response.read() self.logger.debug('Playlist downloaded') matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = config.logomap.get(name) url = itemdict['url'] if logo: itemdict['logo'] = logo if (url.startswith('acestream://')) or ( url.startswith('http://') and url.endswith('.acelive')): self.channels[name] = url itemdict['url'] = urllib2.quote(encname, '') + '.mp4' self.playlist.addItem(itemdict) m.update(encname) self.etag = '"' + m.hexdigest() + '"' except: self.logger.error("Can't download playlist!") self.logger.error(traceback.format_exc()) return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout, p2pconfig.zoneid) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") except: # p2pproxy plugin seems not configured self.updatelogos = False return True
def handle(self, connection): P2pproxy.logger.debug('Handling request') hostport = connection.headers['Host'] query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) if connection.reqtype == 'channels': # /channels/ branch if len(connection.splittedpath) == 3 and connection.splittedpath[2].split('?')[ 0] == 'play': # /channels/play?id=[id] channel_id = self.get_param('id') if not channel_id: # /channels/play?id=&_=[epoch timestamp] is Torrent-TV widget proxy check # P2pProxy simply closes connection on this request sending Server header, so do we if self.get_param('_'): P2pproxy.logger.debug('Status check') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/plain;charset=utf-8') connection.send_header('Server', 'P2pProxy/1.0.3.1 AceProxy') connection.wfile.write('\r\n') return else: connection.dieWithError() # Bad request return stream_url = None session = TorrentTvApi.auth(config.email, config.password) stream_type, stream = TorrentTvApi.stream_source(session, channel_id) if stream_type == 'torrent': stream_url = re.sub('^(http.+)$', lambda match: '/torrent/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub('^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(False) elif self.get_param('type') == 'm3u': # /channels/?filter=[filter]&group=[group]&type=m3u connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() param_group = self.get_param('group') param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, param_filter) playlistgen = PlaylistGenerator() P2pproxy.logger.debug('Generating requested m3u playlist') for channel in translations_list: group_id = channel.getAttribute('group') if param_group and param_group != 'all' and param_group != group_id: # filter channels by group continue name = channel.getAttribute('name') group = TorrentTvApi.CATEGORIES[int(group_id)].decode('utf-8') cid = channel.getAttribute('id') logo = channel.getAttribute('logo') if config.fullpathlogo: logo = 'http://torrent-tv.ru/uploads/' + logo playlistgen.addItem({'name': name, 'url': cid, 'group': group, 'logo': logo}) P2pproxy.logger.debug('Exporting') exported = playlistgen.exportm3u(hostport) exported = exported.encode('utf-8') connection.wfile.write(exported) else: # /channels/?filter=[filter] param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, param_filter, True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Length', str(len(translations_list))) connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == 'xbmc.pvr': # same as /channels request if len(connection.splittedpath) == 3 and connection.splittedpath[2] == 'playlist': session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, 'all', True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Length', str(len(translations_list))) connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == 'archive': # /archive/ branch if len(connection.splittedpath) == 3 and connection.splittedpath[2] == 'channels': # /archive/channels session = TorrentTvApi.auth(config.email, config.password) archive_channels = TorrentTvApi.archive_channels(session, True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Length', str(len(archive_channels))) connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() connection.wfile.write(archive_channels) if len(connection.splittedpath) == 3 and connection.splittedpath[2].split('?')[ 0] == 'play': # /archive/play?id=[record_id] record_id = self.get_param('id') if not record_id: connection.dieWithError() # Bad request return stream_url = None session = TorrentTvApi.auth(config.email, config.password) stream_type, stream = TorrentTvApi.archive_stream_source(session, record_id) if stream_type == 'torrent': stream_url = re.sub('^(http.+)$', lambda match: '/torrent/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub('^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(False) elif self.get_param('type') == 'm3u': # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() param_date = self.get_param('date') if not param_date: d = date.today() # consider default date as today if not given else: try: param_date = param_date.split('-') d = date(param_date[2], param_date[1], param_date[0]) except IndexError: P2pproxy.logger.error('date param is not correct!') connection.dieWithError() return param_channel = self.get_param('channel_id') if param_channel == '' or not param_channel: P2pproxy.logger.error('Got /archive/ request but no channel_id specified!') connection.dieWithError() return session = TorrentTvApi.auth(config.email, config.password) records_list = TorrentTvApi.records(session, param_channel, d.strftime('%d-%m-%Y')) channels_list = TorrentTvApi.archive_channels(session) playlistgen = PlaylistGenerator() P2pproxy.logger.debug('Generating archive m3u playlist') for record in records_list: record_id = record.getAttribute('record_id') name = record.getAttribute('name') channel_id = record.getAttribute('channel_id') channel_name = '' logo = '' for channel in channels_list: if channel.getAttribute('channel_id') == channel_id: channel_name = channel.getAttribute('name') logo = channel.getAttribute('logo') if channel_name != '': name = '(' + channel_name + ') ' + name if logo != '' and config.fullpathlogo: logo = 'http://torrent-tv.ru/uploads/' + logo playlistgen.addItem({'name': name, 'url': record_id, 'logo': logo}) P2pproxy.logger.debug('Exporting') exported = playlistgen.exportm3u(hostport, empty_header=True, archive=True) exported = exported.encode('utf-8') connection.wfile.write(exported) else: # /archive/?date=[param_date]&channel_id=[param_channel] param_date = self.get_param('date') if not param_date: d = date.today() else: try: param_date = param_date.split('-') d = date(param_date[2], param_date[1], param_date[0]) except IndexError: P2pproxy.logger.error('date param is not correct!') connection.dieWithError() return param_channel = self.get_param('channel_id') if param_channel == '' or not param_channel: P2pproxy.logger.error('Got /archive/ request but no channel_id specified!') connection.dieWithError() return session = TorrentTvApi.auth(config.email, config.password) records_list = TorrentTvApi.records(session, param_channel, d.strftime('%d-%m-%Y'), True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Length', str(len(records_list))) connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() connection.wfile.write(records_list)
def handle(self, connection, headers_only=False): P2pproxy.logger.debug('Handling request') hostport = connection.headers['Host'] query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) if connection.reqtype == 'channels' or connection.reqtype == 'channels.m3u': # /channels/ branch if len(connection.splittedpath) == 3 and connection.splittedpath[2].split('?')[ 0] == 'play': # /channels/play?id=[id] channel_id = self.get_param('id') if not channel_id: # /channels/play?id=&_=[epoch timestamp] is Torrent-TV widget proxy check # P2pProxy simply closes connection on this request sending Server header, so do we if self.get_param('_'): P2pproxy.logger.debug('Status check') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/plain;charset=utf-8') connection.send_header('Server', 'P2pProxy/1.0.3.1 AceProxy') connection.wfile.write('\r\n') return else: connection.dieWithError() # Bad request return if headers_only: connection.send_response(200) connection.send_header("Content-Type", "video/mpeg") connection.end_headers() return stream_url = None stream_type, stream = self.api.stream_source(channel_id) if stream_type == 'torrent': stream_url = re.sub('^(http.+)$', lambda match: '/torrent/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub('^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(headers_only, fmt=self.get_param('fmt')) elif connection.reqtype == 'channels.m3u' or self.get_param('type') == 'm3u': # /channels/?filter=[filter]&group=[group]&type=m3u if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() return param_group = self.get_param('group') param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter translations_list = self.api.translations(param_filter) playlistgen = PlaylistGenerator() P2pproxy.logger.debug('Generating requested m3u playlist') for channel in translations_list: group_id = channel.getAttribute('group') if param_group and param_group != 'all' and param_group != group_id: # filter channels by group continue name = channel.getAttribute('name') group = TorrentTvApi.CATEGORIES[int(group_id)].decode('utf-8') cid = channel.getAttribute('id') logo = channel.getAttribute('logo') if config.fullpathlogo: logo = P2pproxy.TTVU + logo fields = {'name': name, 'id': cid, 'url': cid, 'group': group, 'logo': logo} fields['tvgid'] = config.tvgid % fields playlistgen.addItem(fields) P2pproxy.logger.debug('Exporting') header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u(hostport=hostport, header=header, fmt=self.get_param('fmt')) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) else: # /channels/?filter=[filter] if headers_only: connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() return param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter translations_list = self.api.translations(param_filter, True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.send_header('Content-Length', str(len(translations_list))) connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == 'xbmc.pvr': # same as /channels request if len(connection.splittedpath) == 3 and connection.splittedpath[2] == 'playlist': connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() return translations_list = self.api.translations('all', True) connection.send_header('Content-Length', str(len(translations_list))) connection.end_headers() P2pproxy.logger.debug('Exporting') connection.wfile.write(translations_list) elif connection.reqtype == 'archive': # /archive/ branch if len(connection.splittedpath) >= 3 and (connection.splittedpath[2] == 'dates' or connection.splittedpath[2] == 'dates.m3u'): # /archive/dates.m3u d = date.today() delta = timedelta(days=1) playlistgen = PlaylistGenerator() hostport = connection.headers['Host'] days = int(self.get_param('days')) if self.params.has_key('days') else 7 suffix = '&suffix=' + self.get_param('suffix') if self.params.has_key('suffix') else '' for i in range(days): dfmt = d.strftime('%d-%m-%Y') url = 'http://%s/archive/playlist/?date=%s%s' % (hostport, dfmt, suffix) playlistgen.addItem({'group': '', 'tvg': '', 'name': dfmt, 'url': url}) d = d - delta exported = playlistgen.exportm3u(hostport, empty_header=True, process_url=False, fmt=self.get_param('fmt')).encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) return elif len(connection.splittedpath) >= 3 and (connection.splittedpath[2] == 'playlist' or connection.splittedpath[2] == 'playlist.m3u'): # /archive/playlist.m3u dates = list() if self.params.has_key('date'): for d in self.params['date']: dates.append(self.parse_date(d).strftime('%d-%m-%Y').replace('-0', '-')) else: d = date.today() delta = timedelta(days=1) days = int(self.get_param('days')) if self.params.has_key('days') else 7 for i in range(days): dates.append(d.strftime('%d-%m-%Y').replace('-0', '-')) d = d - delta connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') if headers_only: connection.end_headers() return channels_list = self.api.archive_channels() hostport = connection.headers['Host'] playlistgen = PlaylistGenerator() suffix = '&suffix=' + self.get_param('suffix') if self.params.has_key('suffix') else '' for channel in channels_list: epg_id = channel.getAttribute('epg_id') name = channel.getAttribute('name') logo = channel.getAttribute('logo') if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo for d in dates: n = name + ' (' + d + ')' if len(dates) > 1 else name url = 'http://%s/archive/?type=m3u&date=%s&channel_id=%s%s' % (hostport, d, epg_id, suffix) playlistgen.addItem({'group': name, 'tvg': '', 'name': n, 'url': url, 'logo': logo}) exported = playlistgen.exportm3u(hostport, empty_header=True, process_url=False, fmt=self.get_param('fmt')).encode('utf-8') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) return elif len(connection.splittedpath) == 3 and connection.splittedpath[2] == 'channels': # /archive/channels connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() else: archive_channels = self.api.archive_channels(True) P2pproxy.logger.debug('Exporting') connection.send_header('Content-Length', str(len(archive_channels))) connection.end_headers() connection.wfile.write(archive_channels) return if len(connection.splittedpath) == 3 and connection.splittedpath[2].split('?')[ 0] == 'play': # /archive/play?id=[record_id] record_id = self.get_param('id') if not record_id: connection.dieWithError() # Bad request return if headers_only: connection.send_response(200) connection.send_header("Content-Type", "video/mpeg") connection.end_headers() return stream_url = None stream_type, stream = self.api.archive_stream_source(record_id) if stream_type == 'torrent': stream_url = re.sub('^(http.+)$', lambda match: '/torrent/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub('^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote(match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(headers_only, fmt=self.get_param('fmt')) elif self.get_param('type') == 'm3u': # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel] d = self.get_date_param() if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() return playlistgen = PlaylistGenerator() param_channel = self.get_param('channel_id') d = d.strftime('%d-%m-%Y').replace('-0', '-') if param_channel == '' or not param_channel: channels_list = self.api.archive_channels() for channel in channels_list: channel_id = channel.getAttribute('epg_id') try: records_list = self.api.records(channel_id, d) channel_name = channel.getAttribute('name') logo = channel.getAttribute('logo') if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo for record in records_list: name = record.getAttribute('name') record_id = record.getAttribute('record_id') playlistgen.addItem({'group': channel_name, 'tvg': '', 'name': name, 'url': record_id, 'logo': logo}) except: P2pproxy.logger.debug('Failed to load archive for ' + channel_id) else: records_list = self.api.records(param_channel, d) channels_list = self.api.archive_channels() P2pproxy.logger.debug('Generating archive m3u playlist') for record in records_list: record_id = record.getAttribute('record_id') channel_id = record.getAttribute('epg_id') name = record.getAttribute('name') d = time.localtime(float(record.getAttribute('time'))) n = '%.2d:%.2d %s' % (d.tm_hour, d.tm_min, name) logo = '' for channel in channels_list: if channel.getAttribute('epg_id') == channel_id: channel_name = channel.getAttribute('name') logo = channel.getAttribute('logo') if channel_name != '': name = '(' + channel_name + ') ' + name if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo playlistgen.addItem({'group': channel_name, 'name': n, 'url': record_id, 'logo': logo, 'tvg': ''}) P2pproxy.logger.debug('Exporting') exported = playlistgen.exportm3u(hostport, empty_header=True, archive=True, fmt=self.get_param('fmt')) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) else: # /archive/?date=[param_date]&channel_id=[param_channel] param_date = self.get_param('date') if not param_date: d = date.today() else: try: param_date = param_date.split('-') d = date(int(param_date[2]), int(param_date[1]), int(param_date[0])) except IndexError: P2pproxy.logger.error('date param is not correct!') connection.dieWithError() return param_channel = self.get_param('channel_id') if param_channel == '' or not param_channel: P2pproxy.logger.error('Got /archive/ request but no channel_id specified!') connection.dieWithError() return connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() else: records_list = self.api.records(param_channel, d.strftime('%d-%m-%Y'), True) P2pproxy.logger.debug('Exporting') connection.send_header('Content-Length', str(len(records_list))) connection.end_headers() connection.wfile.write(records_list) elif connection.reqtype == 'logos': # Used to generate logomap for the torrenttv plugin translations_list = self.api.translations('all') last = translations_list[-1] connection.send_response(200) connection.send_header('Content-Type', 'text/plain;charset=utf-8') connection.end_headers() connection.wfile.write("logobase = '" + P2pproxy.TTVU + "'\n") connection.wfile.write("logomap = {\n") for channel in translations_list: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') connection.wfile.write(" u'%s': logobase + '%s'" % (name, logo)) if not channel == last: connection.wfile.write(",\n") else: connection.wfile.write("\n") connection.wfile.write("}\n")
def handle(self, connection, headers_only=False): hostport = connection.headers['Host'] if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Connection', 'close') connection.end_headers() return query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) url = None list_type = self.getparam('type') if not list_type or list_type.startswith('ttv'): url = config.url_ttv elif list_type.startswith('mob_ttv'): url = config.url_mob_ttv elif list_type.startswith('allfon'): url = config.url_allfon # 15 minutes cache if not Torrenttelik.playlist or ( int(time.time()) - Torrenttelik.playlisttime > 15 * 60): if not self.downloadPlaylist(url): connection.dieWithError() return try: channels = Torrenttelik.playlist['channels'] except Exception as e: Torrenttelik.logger.error("Can't parse JSON! " + repr(e)) return add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass playlistgen = PlaylistGenerator() for channel in channels: channel['group'] = channel.get('cat', '') playlistgen.addItem(channel) header = '#EXTM3U url-tvg="%s" tvg-shift=%d deinterlace=1 m3uautoload=1 cache=1000\n' % ( config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u( hostport, header=header, add_ts=add_ts, fmt=self.getparam('fmt')).encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8') connection.send_header('Content-Length', str(len(exported))) connection.send_header('Connection', 'close') connection.end_headers() connection.wfile.write(exported)
def handle(self, connection): # 30 minutes cache if not Ttv.playlist or (int(time.time()) - Ttv.playlisttime > 30 * 60): if not self.downloadPlaylist(): connection.dieWithError() return hostport = connection.headers['Host'] connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() # Match playlist with regexp matches = re.finditer(r',(?P<name>\S.+) \((?P<group>.+)\)\n(?P<url>^.+$)', Ttv.playlist, re.MULTILINE) add_ts = False try: if connection.splittedpath[2].lower() == 'ts': add_ts = True except: pass g_filter = False g_name = '' try: if connection.splittedpath[2].lower()[:1] == 'g': #Ttv.logger.debug('Group ' + connection.splittedpath[2].lower() + ' - ' + connection.splittedpath[2].lower()[1:2]) #Ttv.logger.debug(Ttv.CATEGORIES['1']) g_name = Ttv.CATEGORIES[connection.splittedpath[2].lower()[1:2]] g_filter = True #Ttv.logger.debug('Group name ' + g_name) except: pass mg_filter = False; mg_list = [] try: Ttv.logger.debug('Groups path ' + connection.path) query = urlparse.urlparse(urllib2.unquote(connection.path).decode('utf8')).query Ttv.logger.debug('Groups query ' + query) mg_list = urlparse.parse_qs(query)['g'] Ttv.logger.debug('Groups list0 ' + mg_list[0]) mg_filter = True except: pass playlistgen = PlaylistGenerator() for match in matches: itemdict = match.groupdict() gr = itemdict['group'].decode('utf8') if not(g_filter or mg_filter) or (g_filter and (g_name == itemdict['group'])) or (mg_filter and (gr in mg_list)): name = itemdict.get('name').decode('UTF-8') logo = config.logomap.get(name) if logo is not None: itemdict['logo'] = logo playlistgen.addItem(itemdict) header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' %(config.tvgurl, config.tvgshift) connection.wfile.write(playlistgen.exportm3u(hostport, add_ts=add_ts, header=header))
def handle(self, connection): P2pproxy.logger.debug("Handling request") hostport = connection.headers["Host"] query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) if connection.reqtype == "channels": # /channels/ branch if ( len(connection.splittedpath) == 3 and connection.splittedpath[2].split("?")[0] == "play" ): # /channels/play?id=[id] channel_id = self.get_param("id") if not channel_id: # /channels/play?id=&_=[epoch timestamp] is Torrent-TV widget proxy check # P2pProxy simply closes connection on this request sending Server header, so do we if self.get_param("_"): P2pproxy.logger.debug("Status check") connection.send_response(200) connection.send_header("Access-Control-Allow-Origin", "*") connection.send_header("Connection", "close") connection.send_header("Content-Type", "text/plain;charset=utf-8") connection.send_header("Server", "P2pProxy/1.0.3.1 AceProxy") connection.wfile.write("\r\n") return else: connection.dieWithError() # Bad request return stream_url = None session = TorrentTvApi.auth(config.email, config.password) stream_type, stream = TorrentTvApi.stream_source(session, channel_id) if stream_type == "torrent": stream_url = re.sub( "^(http.+)$", lambda match: "/torrent/" + urllib2.quote(match.group(0), "") + "/stream.mp4", stream, ) elif stream_type == "contentid": stream_url = re.sub( "^([0-9a-f]{40})", lambda match: "/pid/" + urllib2.quote(match.group(0), "") + "/stream.mp4", stream, ) connection.path = stream_url connection.splittedpath = stream_url.split("/") connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(False) elif self.get_param("type") == "m3u": # /channels/?filter=[filter]&group=[group]&type=m3u connection.send_response(200) connection.send_header("Content-Type", "application/x-mpegurl") connection.end_headers() param_group = self.get_param("group") param_filter = self.get_param("filter") if not param_filter: param_filter = "all" # default filter session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, param_filter) playlistgen = PlaylistGenerator() P2pproxy.logger.debug("Generating requested m3u playlist") for channel in translations_list: group_id = channel.getAttribute("group") if param_group and param_group != "all" and param_group != group_id: # filter channels by group continue name = channel.getAttribute("name") group = TorrentTvApi.CATEGORIES[int(group_id)].decode("utf-8") cid = channel.getAttribute("id") logo = channel.getAttribute("logo") if config.fullpathlogo: logo = "http://torrent-tv.ru/uploads/" + logo fields = {"name": name, "id": cid, "url": cid, "group": group, "logo": logo} fields["tvgid"] = config.tvgid % fields playlistgen.addItem(fields) P2pproxy.logger.debug("Exporting") header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % (config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u(hostport=hostport, header=header) exported = exported.encode("utf-8") connection.wfile.write(exported) else: # /channels/?filter=[filter] param_filter = self.get_param("filter") if not param_filter: param_filter = "all" # default filter session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, param_filter, True) P2pproxy.logger.debug("Exporting") connection.send_response(200) connection.send_header("Access-Control-Allow-Origin", "*") connection.send_header("Connection", "close") connection.send_header("Content-Length", str(len(translations_list))) connection.send_header("Content-Type", "text/xml;charset=utf-8") connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == "xbmc.pvr": # same as /channels request if len(connection.splittedpath) == 3 and connection.splittedpath[2] == "playlist": session = TorrentTvApi.auth(config.email, config.password) translations_list = TorrentTvApi.translations(session, "all", True) P2pproxy.logger.debug("Exporting") connection.send_response(200) connection.send_header("Access-Control-Allow-Origin", "*") connection.send_header("Connection", "close") connection.send_header("Content-Length", str(len(translations_list))) connection.send_header("Content-Type", "text/xml;charset=utf-8") connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == "archive": # /archive/ branch if len(connection.splittedpath) == 3 and connection.splittedpath[2] == "channels": # /archive/channels session = TorrentTvApi.auth(config.email, config.password) archive_channels = TorrentTvApi.archive_channels(session, True) P2pproxy.logger.debug("Exporting") connection.send_response(200) connection.send_header("Access-Control-Allow-Origin", "*") connection.send_header("Connection", "close") connection.send_header("Content-Length", str(len(archive_channels))) connection.send_header("Content-Type", "text/xml;charset=utf-8") connection.end_headers() connection.wfile.write(archive_channels) if ( len(connection.splittedpath) == 3 and connection.splittedpath[2].split("?")[0] == "play" ): # /archive/play?id=[record_id] record_id = self.get_param("id") if not record_id: connection.dieWithError() # Bad request return stream_url = None session = TorrentTvApi.auth(config.email, config.password) stream_type, stream = TorrentTvApi.archive_stream_source(session, record_id) if stream_type == "torrent": stream_url = re.sub( "^(http.+)$", lambda match: "/torrent/" + urllib2.quote(match.group(0), "") + "/stream.mp4", stream, ) elif stream_type == "contentid": stream_url = re.sub( "^([0-9a-f]{40})", lambda match: "/pid/" + urllib2.quote(match.group(0), "") + "/stream.mp4", stream, ) connection.path = stream_url connection.splittedpath = stream_url.split("/") connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(False) elif self.get_param("type") == "m3u": # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel] connection.send_response(200) connection.send_header("Content-Type", "application/x-mpegurl") connection.end_headers() param_date = self.get_param("date") if not param_date: d = date.today() # consider default date as today if not given else: try: param_date = param_date.split("-") d = date(param_date[2], param_date[1], param_date[0]) except IndexError: P2pproxy.logger.error("date param is not correct!") connection.dieWithError() return param_channel = self.get_param("channel_id") if param_channel == "" or not param_channel: P2pproxy.logger.error("Got /archive/ request but no channel_id specified!") connection.dieWithError() return session = TorrentTvApi.auth(config.email, config.password) records_list = TorrentTvApi.records(session, param_channel, d.strftime("%d-%m-%Y")) channels_list = TorrentTvApi.archive_channels(session) playlistgen = PlaylistGenerator() P2pproxy.logger.debug("Generating archive m3u playlist") for record in records_list: record_id = record.getAttribute("record_id") name = record.getAttribute("name") channel_id = record.getAttribute("channel_id") channel_name = "" logo = "" for channel in channels_list: if channel.getAttribute("channel_id") == channel_id: channel_name = channel.getAttribute("name") logo = channel.getAttribute("logo") if channel_name != "": name = "(" + channel_name + ") " + name if logo != "" and config.fullpathlogo: logo = "http://torrent-tv.ru/uploads/" + logo playlistgen.addItem({"name": name, "url": record_id, "logo": logo}) P2pproxy.logger.debug("Exporting") exported = playlistgen.exportm3u(hostport, empty_header=True, archive=True) exported = exported.encode("utf-8") connection.wfile.write(exported) else: # /archive/?date=[param_date]&channel_id=[param_channel] param_date = self.get_param("date") if not param_date: d = date.today() else: try: param_date = param_date.split("-") d = date(param_date[2], param_date[1], param_date[0]) except IndexError: P2pproxy.logger.error("date param is not correct!") connection.dieWithError() return param_channel = self.get_param("channel_id") if param_channel == "" or not param_channel: P2pproxy.logger.error("Got /archive/ request but no channel_id specified!") connection.dieWithError() return session = TorrentTvApi.auth(config.email, config.password) records_list = TorrentTvApi.records(session, param_channel, d.strftime("%d-%m-%Y"), True) P2pproxy.logger.debug("Exporting") connection.send_response(200) connection.send_header("Access-Control-Allow-Origin", "*") connection.send_header("Connection", "close") connection.send_header("Content-Length", str(len(records_list))) connection.send_header("Content-Type", "text/xml;charset=utf-8") connection.end_headers() connection.wfile.write(records_list)
def downloadPlaylist(self): headers = { 'User-Agent': 'Magic Browser', 'Accept-Encoding': 'gzip,deflate', 'Connection': 'close' } try: if config.useproxy: origin = requests.get(config.url, headers=headers, proxies=config.proxies, timeout=30).text.encode('UTF-8') else: origin = requests.get(config.url, headers=headers, timeout=10).text.encode('UTF-8') self.logger.info('TTV playlist ' + config.url + ' downloaded') matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = self.logomap.get(name) url = itemdict['url'] if logo: itemdict['logo'] = logo if url.startswith('acestream://') or url.startswith('infohash://') \ or (url.startswith('http://') and url.endswith('.acelive')) \ or (url.startswith('http://') and url.endswith('.torrent')): self.channels[name] = url itemdict['url'] = requests.utils.quote(encname, '') + '.mp4' self.playlist.addItem(itemdict) m.update(encname) self.etag = '"' + m.hexdigest() + '"' except requests.exceptions.ConnectionError: self.logger.error("Can't download TTV playlist!") return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout, p2pconfig.zoneid) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") self.updatelogos = False except: # p2pproxy plugin seems not configured self.updatelogos = False return True
class Torrenttv(AceProxyPlugin): # ttvplaylist handler is obsolete handlers = ( 'torrenttv', 'ttvplaylist', ) def __init__(self, AceConfig, AceStuff): self.logger = logging.getLogger('plugin_torrenttv') self.lock = threading.Lock() self.channels = None self.playlist = None self.playlisttime = None self.etag = None self.logomap = config.logomap self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe' if config.updateevery: gevent.spawn(self.playlistTimedDownloader) def playlistTimedDownloader(self): while True: time.sleep(10) with self.lock: self.downloadPlaylist() gevent.sleep(config.updateevery * 60) def downloadPlaylist(self): headers = { 'User-Agent': 'Magic Browser', 'Accept-Encoding': 'gzip,deflate', 'Connection': 'close' } try: if config.useproxy: origin = requests.get(config.url, headers=headers, proxies=config.proxies, timeout=30).text.encode('UTF-8') else: origin = requests.get(config.url, headers=headers, timeout=10).text.encode('UTF-8') self.logger.info('TTV playlist ' + config.url + ' downloaded') matches = re.finditer( r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?', origin, re.MULTILINE) self.playlisttime = int(time.time()) self.playlist = PlaylistGenerator() self.channels = dict() m = md5.new() for match in matches: itemdict = match.groupdict() encname = itemdict.get('name') name = encname.decode('UTF-8') logo = self.logomap.get(name) url = itemdict['url'] if logo: itemdict['logo'] = logo if url.startswith('acestream://') or url.startswith('infohash://') \ or (url.startswith('http://') and url.endswith('.acelive')) \ or (url.startswith('http://') and url.endswith('.torrent')): self.channels[name] = url itemdict['url'] = requests.utils.quote(encname, '') + '.mp4' self.playlist.addItem(itemdict) m.update(encname) self.etag = '"' + m.hexdigest() + '"' except requests.exceptions.ConnectionError: self.logger.error("Can't download TTV playlist!") return False if self.updatelogos: try: api = TorrentTvApi(p2pconfig.email, p2pconfig.password, p2pconfig.sessiontimeout, p2pconfig.zoneid) translations = api.translations('all') logos = dict() for channel in translations: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') logos[name] = config.logobase + logo self.logomap = logos self.logger.debug("Logos updated") self.updatelogos = False except: # p2pproxy plugin seems not configured self.updatelogos = False return True def handle(self, connection, headers_only=False): play = False with self.lock: # N minutes cache self.cache = 30 if not self.playlist or (int(time.time()) - self.playlisttime > self.cache * 60): self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe' if not self.downloadPlaylist(): connection.dieWithError() return url = urlparse.urlparse(connection.path) path = url.path[0:-1] if url.path.endswith('/') else url.path params = urlparse.parse_qs(url.query) fmt = params['fmt'][0] if params.has_key('fmt') else None if path.startswith('/torrenttv/channel/'): if not path.endswith('.mp4'): connection.dieWithError(404, 'Invalid path: ' + path, logging.DEBUG) return name = requests.utils.unquote(path[19:-4]).decode('UTF8') url = self.channels.get(name) if not url: connection.dieWithError(404, 'Unknown channel: ' + name, logging.DEBUG) return elif url.startswith('acestream://'): connection.path = '/pid/' + url[12:] + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'pid' elif url.startswith('infohash://'): connection.path = '/infohash/' + url[11:] + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'infohash' elif url.startswith('http://') and (url.endswith('.torrent') or url.endswith('.acelive')): connection.path = '/torrent/' + requests.utils.quote( url, '') + '/stream.mp4' connection.splittedpath = connection.path.split('/') connection.reqtype = 'torrent' play = True elif self.etag == connection.headers.get('If-None-Match'): self.logger.debug('ETag matches - returning 304') connection.send_response(304) connection.send_header('Connection', 'close') connection.end_headers() return else: hostport = connection.headers['Host'] path = '' if len(self.channels) == 0 else '/torrenttv/channel' add_ts = True if path.endswith('/ts') else False header = '#EXTM3U url-tvg="%s" tvg-shift=%d deinterlace=1 m3uautoload=1 cache=1000\n' % ( config.tvgurl, config.tvgshift) exported = self.playlist.exportm3u(hostport, path, add_ts=add_ts, header=header, fmt=fmt) connection.send_response(200) connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8') connection.send_header('ETag', self.etag) connection.send_header('Content-Length', str(len(exported))) connection.send_header('Connection', 'close') connection.end_headers() if play: connection.handleRequest(headers_only, name, config.logomap.get(name), fmt=fmt) elif not headers_only: connection.wfile.write(exported)
def handle(self, connection, headers_only=False): P2pproxy.logger.debug('Handling request') hostport = connection.headers['Host'] query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) if connection.reqtype == 'channels' or connection.reqtype == 'channels.m3u': # /channels/ branch if len(connection.splittedpath) == 3 and connection.splittedpath[ 2].split('?')[0] == 'play': # /channels/play?id=[id] channel_id = self.get_param('id') if not channel_id: # /channels/play?id=&_=[epoch timestamp] is Torrent-TV widget proxy check # P2pProxy simply closes connection on this request sending Server header, so do we if self.get_param('_'): P2pproxy.logger.debug('Status check') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/plain;charset=utf-8') connection.send_header('Server', 'P2pProxy/1.0.4.4 AceProxy') connection.wfile.write('\r\n') return else: connection.dieWithError() # Bad request return if headers_only: connection.send_response(200) connection.send_header("Content-Type", "video/mpeg") connection.end_headers() return stream_url = None stream_type, stream, translations_list = self.api.stream_source( channel_id) name = logo = '' for channel in translations_list: if channel.getAttribute('id') == channel_id: name = channel.getAttribute('name') logo = channel.getAttribute('logo') if config.fullpathlogo: logo = P2pproxy.TTVU + logo break if stream_type == 'torrent': stream_url = re.sub( '^(http.+)$', lambda match: '/torrent/' + urllib2.quote( match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub( '^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote( match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(headers_only, name, logo, fmt=self.get_param('fmt')) elif connection.reqtype == 'channels.m3u' or self.get_param( 'type' ) == 'm3u': # /channels/?filter=[filter]&group=[group]&type=m3u if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() return param_group = self.params.get('group') param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter if param_group: if 'all' in param_group: param_group = None else: tmp = [] for g in param_group: tmp += g.split(',') param_group = tmp translations_list = self.api.translations(param_filter) playlistgen = PlaylistGenerator() P2pproxy.logger.debug('Generating requested m3u playlist') for channel in translations_list: group_id = channel.getAttribute('group') if param_group and not group_id in param_group: # filter channels by group continue name = channel.getAttribute('name') group = TorrentTvApi.CATEGORIES[int(group_id)].decode( 'utf-8') cid = channel.getAttribute('id') logo = channel.getAttribute('logo') if config.fullpathlogo: logo = P2pproxy.TTVU + logo fields = { 'name': name, 'id': cid, 'url': cid, 'group': group, 'logo': logo } fields['tvgid'] = config.tvgid % fields playlistgen.addItem(fields) P2pproxy.logger.debug('Exporting') header = '#EXTM3U url-tvg="%s" tvg-shift=%d\n' % ( config.tvgurl, config.tvgshift) exported = playlistgen.exportm3u(hostport=hostport, header=header, fmt=self.get_param('fmt')) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) else: # /channels/?filter=[filter] if headers_only: connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.end_headers() return param_filter = self.get_param('filter') if not param_filter: param_filter = 'all' # default filter translations_list = self.api.translations(param_filter, True) P2pproxy.logger.debug('Exporting') connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') connection.send_header('Content-Length', str(len(translations_list))) connection.end_headers() connection.wfile.write(translations_list) elif connection.reqtype == 'xbmc.pvr': # same as /channels request if len(connection.splittedpath ) == 3 and connection.splittedpath[2] == 'playlist': connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() return translations_list = self.api.translations('all', True) connection.send_header('Content-Length', str(len(translations_list))) connection.end_headers() P2pproxy.logger.debug('Exporting') connection.wfile.write(translations_list) elif connection.reqtype == 'archive': # /archive/ branch if len(connection.splittedpath) >= 3 and ( connection.splittedpath[2] == 'dates' or connection.splittedpath[2] == 'dates.m3u'): # /archive/dates.m3u d = date.today() delta = timedelta(days=1) playlistgen = PlaylistGenerator() hostport = connection.headers['Host'] days = int(self.get_param('days')) if self.params.has_key( 'days') else 7 suffix = '&suffix=' + self.get_param( 'suffix') if self.params.has_key('suffix') else '' for i in range(days): dfmt = d.strftime('%d-%m-%Y') url = 'http://%s/archive/playlist/?date=%s%s' % ( hostport, dfmt, suffix) playlistgen.addItem({ 'group': '', 'tvg': '', 'name': dfmt, 'url': url }) d = d - delta exported = playlistgen.exportm3u( hostport, empty_header=True, process_url=False, fmt=self.get_param('fmt')).encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) return elif len(connection.splittedpath) >= 3 and ( connection.splittedpath[2] == 'playlist' or connection.splittedpath[2] == 'playlist.m3u'): # /archive/playlist.m3u dates = list() if self.params.has_key('date'): for d in self.params['date']: dates.append( self.parse_date(d).strftime('%d-%m-%Y').replace( '-0', '-')) else: d = date.today() delta = timedelta(days=1) days = int(self.get_param('days')) if self.params.has_key( 'days') else 7 for i in range(days): dates.append(d.strftime('%d-%m-%Y').replace('-0', '-')) d = d - delta connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') if headers_only: connection.end_headers() return channels_list = self.api.archive_channels() hostport = connection.headers['Host'] playlistgen = PlaylistGenerator() suffix = '&suffix=' + self.get_param( 'suffix') if self.params.has_key('suffix') else '' for channel in channels_list: epg_id = channel.getAttribute('epg_id') name = channel.getAttribute('name') logo = channel.getAttribute('logo') if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo for d in dates: n = name + ' (' + d + ')' if len(dates) > 1 else name url = 'http://%s/archive/?type=m3u&date=%s&channel_id=%s%s' % ( hostport, d, epg_id, suffix) playlistgen.addItem({ 'group': name, 'tvg': '', 'name': n, 'url': url, 'logo': logo }) exported = playlistgen.exportm3u( hostport, empty_header=True, process_url=False, fmt=self.get_param('fmt')).encode('utf-8') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) return elif len(connection.splittedpath) == 3 and connection.splittedpath[ 2] == 'channels': # /archive/channels connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() else: archive_channels = self.api.archive_channels(True) P2pproxy.logger.debug('Exporting') connection.send_header('Content-Length', str(len(archive_channels))) connection.end_headers() connection.wfile.write(archive_channels) return if len(connection.splittedpath) == 3 and connection.splittedpath[ 2].split('?')[0] == 'play': # /archive/play?id=[record_id] record_id = self.get_param('id') if not record_id: connection.dieWithError() # Bad request return if headers_only: connection.send_response(200) connection.send_header("Content-Type", "video/mpeg") connection.end_headers() return stream_url = None stream_type, stream = self.api.archive_stream_source(record_id) if stream_type == 'torrent': stream_url = re.sub( '^(http.+)$', lambda match: '/torrent/' + urllib2.quote( match.group(0), '') + '/stream.mp4', stream) elif stream_type == 'contentid': stream_url = re.sub( '^([0-9a-f]{40})', lambda match: '/pid/' + urllib2.quote( match.group(0), '') + '/stream.mp4', stream) connection.path = stream_url connection.splittedpath = stream_url.split('/') connection.reqtype = connection.splittedpath[1].lower() connection.handleRequest(headers_only, fmt=self.get_param('fmt')) elif self.get_param( 'type' ) == 'm3u': # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel] d = self.get_date_param() if headers_only: connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.end_headers() return playlistgen = PlaylistGenerator() param_channel = self.get_param('channel_id') d = d.strftime('%d-%m-%Y').replace('-0', '-') if param_channel == '' or not param_channel: channels_list = self.api.archive_channels() for channel in channels_list: channel_id = channel.getAttribute('epg_id') try: records_list = self.api.records(channel_id, d) channel_name = channel.getAttribute('name') logo = channel.getAttribute('logo') if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo for record in records_list: name = record.getAttribute('name') record_id = record.getAttribute('record_id') playlistgen.addItem({ 'group': channel_name, 'tvg': '', 'name': name, 'url': record_id, 'logo': logo }) except: P2pproxy.logger.debug( 'Failed to load archive for ' + channel_id) else: records_list = self.api.records(param_channel, d) channels_list = self.api.archive_channels() P2pproxy.logger.debug('Generating archive m3u playlist') for record in records_list: record_id = record.getAttribute('record_id') channel_id = record.getAttribute('epg_id') name = record.getAttribute('name') d = time.localtime(float(record.getAttribute('time'))) n = '%.2d:%.2d %s' % (d.tm_hour, d.tm_min, name) logo = '' for channel in channels_list: if channel.getAttribute('epg_id') == channel_id: channel_name = channel.getAttribute('name') logo = channel.getAttribute('logo') if channel_name != '': name = '(' + channel_name + ') ' + name if logo != '' and config.fullpathlogo: logo = P2pproxy.TTVU + logo playlistgen.addItem({ 'group': channel_name, 'name': n, 'url': record_id, 'logo': logo, 'tvg': '' }) P2pproxy.logger.debug('Exporting') exported = playlistgen.exportm3u(hostport, empty_header=True, archive=True, fmt=self.get_param('fmt')) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/x-mpegurl') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported) else: # /archive/?date=[param_date]&channel_id=[param_channel] param_date = self.get_param('date') if not param_date: d = date.today() else: try: param_date = param_date.split('-') d = date(int(param_date[2]), int(param_date[1]), int(param_date[0])) except IndexError: P2pproxy.logger.error('date param is not correct!') connection.dieWithError() return param_channel = self.get_param('channel_id') if param_channel == '' or not param_channel: P2pproxy.logger.error( 'Got /archive/ request but no channel_id specified!') connection.dieWithError() return connection.send_response(200) connection.send_header('Access-Control-Allow-Origin', '*') connection.send_header('Connection', 'close') connection.send_header('Content-Type', 'text/xml;charset=utf-8') if headers_only: connection.end_headers() else: records_list = self.api.records(param_channel, d.strftime('%d-%m-%Y'), True) P2pproxy.logger.debug('Exporting') connection.send_header('Content-Length', str(len(records_list))) connection.end_headers() connection.wfile.write(records_list) elif connection.reqtype == 'logos': # Used to generate logomap for the torrenttv plugin translations_list = self.api.translations('all') last = translations_list[-1] connection.send_response(200) connection.send_header('Content-Type', 'text/plain;charset=utf-8') connection.end_headers() connection.wfile.write("logobase = '" + P2pproxy.TTVU + "'\n") connection.wfile.write("logomap = {\n") for channel in translations_list: name = channel.getAttribute('name').encode('utf-8') logo = channel.getAttribute('logo').encode('utf-8') connection.wfile.write(" u'%s': logobase + '%s'" % (name, logo)) if not channel == last: connection.wfile.write(",\n") else: connection.wfile.write("\n") connection.wfile.write("}\n")
def handle(self, connection, headers_only=False): query = urlparse.urlparse(connection.path).query self.params = urlparse.parse_qs(query) self.logger.debug('connection.reqtype=%s' % connection.reqtype) self.logger.debug(len(connection.splittedpath)) self.logger.debug('connection.splittedpath=%s' % connection.splittedpath) self.logger.debug('params=%s' % self.params) if connection.reqtype == 'rutor': if len(connection.splittedpath) < 2: connection.send_response(404) connection.send_header('Connection', 'close') connection.end_headers() return if len(connection.splittedpath) in (2, 3): # View Categories playlist = PlaylistGenerator() for cat in config.categories: Title = "[%s]" % cat[1] itemdict = { 'title': Title, 'url': '/rutor/category/%s/' % cat[0], 'description_title': Title, 'description': '', 'type': 'channel' } playlist.addItem(itemdict) self.send_playlist(connection, playlist) if len(connection.splittedpath) == 5: if connection.splittedpath[2] == 'category': category = connection.splittedpath[3] self.logger.debug('Get category: %s' % category) # category = '1' sort = '0' text = '0' try: page = self.params['page'][0] except: page = '1' try: sort = self.params['sort'][0] except: sort = '0' spr = ["", "", "", "", "", ""] playlist = get_rutor_playlist(category, sort, text, spr, page) self.send_playlist(connection, playlist) if connection.splittedpath[2] == 'list': playlist = PlaylistGenerator() torrent_url = connection.splittedpath[3] torrent_url_unquoted = urllib2.unquote( connection.splittedpath[3]) self.logger.debug('list: "%s"' % torrent_url_unquoted) contentinfo = None with self.AceStuff.clientcounter.lock: if not self.AceStuff.clientcounter.idleace: self.AceStuff.clientcounter.idleace = self.AceStuff.clientcounter.createAce( ) contentinfo = self.AceStuff.clientcounter.idleace.GETCONTENTINFO( 'TORRENT', torrent_url_unquoted) if contentinfo and contentinfo.get('status') in ( 1, 2) and contentinfo.get('files'): files = contentinfo.get('files') files.sort() for filename, fid in files: Title = "[%s]" % filename itemdict = { 'title': Title, 'url': '/playtorrent/%s/%s/%s.avi' % (torrent_url, fid, filename), 'description_title': Title, 'description': '', 'type': 'stream' } playlist.addItem(itemdict) else: Title = "[Not found files for play]" itemdict = { 'title': Title, 'url': '/rutor/list/%s/' % torrent_url, 'description_title': Title, 'description': '', 'type': 'channel', } playlist.addItem(itemdict) hostport = connection.headers['Host'] exported = playlist.exportxml(hostport) exported = exported.encode('utf-8') connection.send_response(200) connection.send_header('Content-Type', 'application/xml') connection.send_header('Content-Length', str(len(exported))) connection.end_headers() connection.wfile.write(exported)