Example #1
0
    def handle(self, connection, headers_only=False):

        hostport = connection.headers['Host']
        if headers_only:
            connection.send_response(200)
            connection.send_header('Content-Type',
                                   'audio/mpegurl; charset=utf-8')
            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

        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)

        Allfon.logger.debug('Generating requested m3u playlist')

        pattern = requests.auth.re.compile(
            r',(?P<name>.+)[\r\n].+[\r\n].+[\r\n](?P<url>[^\r\n]+)?')
        for match in pattern.finditer(Allfon.playlist.text,
                                      requests.auth.re.MULTILINE):
            playlistgen.addItem(match.groupdict())

        Allfon.logger.debug('Exporting m3u playlist')
        params = parse_qs(connection.query)
        add_ts = True if connection.path.endswith('/ts') else False

        exported = playlistgen.exportm3u(hostport,
                                         header=config.m3uheadertemplate,
                                         add_ts=add_ts,
                                         fmt=params.get(
                                             'fmt', [''])[0]).encode('utf-8')

        connection.send_response(200)
        connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8')
        connection.send_header('Access-Control-Allow-Origin', '*')
        try:
            h = connection.headers.get('Accept-Encoding').split(',')[0]
            compress_method = {
                'zlib': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS),
                'deflate': zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS),
                'gzip': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16)
            }
            exported = compress_method[h].compress(
                exported) + compress_method[h].flush()
            connection.send_header('Content-Encoding', h)
        except:
            pass
        connection.send_header('Content-Length', len(exported))
        connection.send_header('Connection', 'close')
        connection.end_headers()

        connection.wfile.write(exported)
Example #2
0
    def Playlistparser(self):
        try:
            s = requests.Session()
            s.mount('file://', FileAdapter())
            with s.get(config.url,
                       headers=self.headers,
                       proxies=config.proxies,
                       stream=False,
                       timeout=30) as playlist:
                if playlist.status_code != 304:
                    if playlist.encoding is None: playlist.encoding = 'utf-8'
                    playlist = playlist.json()
                    self.headers['If-Modified-Since'] = gevent.time.strftime(
                        '%a, %d %b %Y %H:%M:%S %Z',
                        gevent.time.gmtime(self.playlisttime))
                    self.playlist = PlaylistGenerator(
                        m3uchanneltemplate=config.m3uchanneltemplate)
                    self.picons = picons.logomap
                    self.channels = {}
                    m = requests.auth.hashlib.md5()
                    logging.info('[%s]: playlist %s downloaded' %
                                 (self.__class__.__name__, config.url))
                    try:
                        urlpattern = requests.utils.re.compile(
                            r'^(acestream|infohash)://[0-9a-f]{40}$|^(http|https)://.*.(acelive|acestream|acemedia|torrent)$'
                        )
                        for channel in playlist['channels']:
                            name = channel['name']
                            url = 'infohash://{url}'.format(**channel)
                            channel['group'] = channel.pop('cat')
                            channel['logo'] = self.picons[name] = channel.get(
                                'logo', picons.logomap.get(name))
                            channel['tvgid'] = channel.pop('program')

                            if requests.utils.re.search(urlpattern, url):
                                self.channels[name] = url
                                channel['url'] = quote(ensure_str(name), '')

                            self.playlist.addItem(channel)
                            m.update(ensure_binary(name))

                    except Exception as e:
                        logging.error("[%s]: can't parse JSON! %s" %
                                      (self.__class__.__name__, repr(e)))
                        return False

                    self.etag = '"' + m.hexdigest() + '"'
                    logging.debug('[%s]: plugin playlist generated' %
                                  self.__class__.__name__)

                self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
            logging.error("[%s]: can't download %s playlist!" %
                          (self.__class__.__name__, config.url))
            return False
        except:
            logging.error(traceback.format_exc())
            return False
    def Playlistparser(self):
        try:
            s = requests.Session()
            s.mount('file://', FileAdapter())
            with s.get(config.url,
                       headers=self.headers,
                       proxies=config.proxies,
                       stream=False,
                       timeout=30) as r:
                if r.status_code != 304:
                    if r.encoding is None: r.encoding = 'utf-8'
                    self.headers['If-Modified-Since'] = gevent.time.strftime(
                        '%a, %d %b %Y %H:%M:%S %Z',
                        gevent.time.gmtime(self.playlisttime))
                    self.playlist = PlaylistGenerator(
                        m3uchanneltemplate=config.m3uchanneltemplate)
                    self.picons = picons.logomap
                    self.channels = {}
                    m = requests.auth.hashlib.md5()
                    logging.info('[%s]: playlist %s downloaded' %
                                 (self.__class__.__name__, config.url))
                    pattern = requests.utils.re.compile(
                        r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?'
                    )
                    urlpattern = requests.utils.re.compile(
                        r'^(acestream|infohash)://[0-9a-f]{40}$|^(http|https)://.*.(acelive|acestream|acemedia|torrent)$'
                    )
                    for match in pattern.finditer(r.text,
                                                  requests.auth.re.MULTILINE):
                        itemdict = match.groupdict()
                        name = itemdict.get('name', '')
                        itemdict['logo'] = self.picons[name] = itemdict.get(
                            'logo', picons.logomap.get(name))
                        url = itemdict['url']

                        if requests.utils.re.search(urlpattern, url):
                            self.channels[name] = url
                            itemdict['url'] = quote(ensure_str(name), '')

                        self.playlist.addItem(itemdict)
                        m.update(ensure_binary(name))

                    self.etag = '"' + m.hexdigest() + '"'
                    logging.debug('[%s]: plugin playlist generated' %
                                  self.__class__.__name__)

                self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
            logging.error("[%s]: can't download %s playlist!" %
                          (self.__class__.__name__, config.url))
            return False
        except:
            logging.error(traceback.format_exc())
            return False

        return True
Example #4
0
    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(connection.path).query
        self.params = 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.json()['channels']
        except Exception as e:
            Torrenttelik.logger.error("Can't parse JSON! %s" % 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)
Example #5
0
    def Playlistparser(self):
        try:
            with requests.get(config.url,
                              headers=self.headers,
                              proxies=config.proxies,
                              stream=False,
                              timeout=30) as playlist:
                if playlist.status_code != 304:
                    if playlist.encoding is None: playlist.encoding = 'utf-8'
                    self.headers['If-Modified-Since'] = gevent.time.strftime(
                        '%a, %d %b %Y %H:%M:%S %Z',
                        gevent.time.gmtime(self.playlisttime))
                    self.playlist = PlaylistGenerator(
                        m3uchanneltemplate=config.m3uchanneltemplate)
                    self.picons = picons.logomap
                    self.channels = {}
                    m = requests.auth.hashlib.md5()
                    self.logger.info('Playlist %s downloaded' % config.url)
                    try:
                        for channel in playlist.json()['channels']:
                            channel['name'] = name = channel.get('name', '')
                            channel[
                                'url'] = url = 'acestream://%s' % channel.get(
                                    'url')
                            channel['group'] = channel.get('cat')
                            if not 'logo' in channel:
                                channel['logo'] = picons.logomap.get(name)
                            self.picons[name] = channel['logo']

                            if url.startswith(('acestream://', 'infohash://')) \
                                  or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                                self.channels[name] = url
                                channel['url'] = quote(
                                    ensure_str(name) + '.ts', '')

                            self.playlist.addItem(channel)
                            m.update(name.encode('utf-8'))

                    except Exception as e:
                        self.logger.error("Can't parse JSON! %s" % repr(e))
                        return

                    self.etag = '"' + m.hexdigest() + '"'
                    self.logger.debug('torrent-telik.m3u playlist generated')

                self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
            self.logger.error("Can't download %s playlist!" % config.url)
            return False
        except:
            self.logger.error(traceback.format_exc())
            return False

        return True
    def downloadPlaylist(self):
        headers = {'User-Agent': 'Magic Browser'}
        try:
            origin = requests.get(config.url, headers=headers, proxies=config.proxies, timeout=30).text.encode('utf-8')

            self.logger.info('TTV playlist %s downloaded' % config.url)
            self.playlisttime = int(time.time())
            self.playlist = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate)
            self.channels = dict()
            m = hashlib.md5()
            if self.updatelogos:
                try:
                    translations_list = TorrentTvApi(p2pconfig.email, p2pconfig.password).translations('all')
                    for channel in translations_list:
                        name = channel.getAttribute('name').encode('utf-8')
                        logo = channel.getAttribute('logo').encode('utf-8')
                        if channel.getAttribute('epg_id') not in ('0', '', ' '):
                           self.epg_id[name.decode('utf-8')] = 'ttv%s' % channel.getAttribute('id').encode('utf-8')
                        if not name.decode('utf-8') in self.logomap:
                           self.logomap[name.decode('utf-8')] = config.logobase + logo

                    self.logger.debug("Logos updated")
                    self.updatelogos = False
                except: self.updatelogos = False # p2pproxy plugin seems not configured

            self.logger.debug('Generating requested m3u playlist')
            pattern = re.compile(r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?')

            for match in pattern.finditer(origin, re.MULTILINE):
                itemdict = match.groupdict()
                encname = itemdict.get('name')
                name = encname.decode('utf-8')

                logo = self.logomap.get(name)
                itemdict['logo'] = logo if logo else 'http://static.acestream.net/sites/acestream/img/ACE-logo.png'

                tvgid = self.epg_id.get(name)
                if tvgid: itemdict['tvgid'] = tvgid

                url = itemdict['url']
                if url.startswith(('acestream://', 'infohash://')) \
                      or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                    self.channels[name] = url
                    itemdict['url'] = requests.compat.quote(encname,'') + '.ts'

                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
        except: self.logger.error(traceback.format_exc()); return False

        return True
Example #7
0
    def Playlistparser(self):
        try:
            s = requests.Session()
            s.mount('file://', FileAdapter())
            with s.get(config.url,
                       headers=self.headers,
                       proxies=config.proxies,
                       stream=False,
                       timeout=30) as r:
                if r.status_code != 304:
                    if r.encoding is None: r.encoding = 'utf-8'
                    self.headers['If-Modified-Since'] = gevent.time.strftime(
                        '%a, %d %b %Y %H:%M:%S %Z',
                        gevent.time.gmtime(self.playlisttime))
                    self.playlist = PlaylistGenerator(
                        m3uchanneltemplate=config.m3uchanneltemplate)
                    self.picons = picons.logomap
                    self.channels = {}
                    m = requests.auth.hashlib.md5()
                    self.logger.info('Playlist %s downloaded' % config.url)
                    pattern = requests.auth.re.compile(
                        r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?'
                    )
                    for match in pattern.finditer(r.text,
                                                  requests.auth.re.MULTILINE):
                        itemdict = match.groupdict()
                        name = itemdict.get('name', '')
                        if not 'logo' in itemdict:
                            itemdict['logo'] = picons.logomap.get(name)
                        self.picons[name] = itemdict['logo']

                        url = itemdict['url']
                        if url.startswith(('acestream://', 'infohash://')) \
                             or (url.startswith(('http://','https://')) and url.endswith(('.acelive', '.acestream', '.acemedia', '.torrent'))):
                            self.channels[name] = url
                            itemdict['url'] = quote(ensure_str('%s.ts' % name),
                                                    '')

                        self.playlist.addItem(itemdict)
                        m.update(name.encode('utf-8'))

                    self.etag = '"' + m.hexdigest() + '"'
                    self.logger.debug('torrenttv.m3u playlist generated')

                self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
            self.logger.error("Can't download %s playlist!" % config.url)
            return False
        except:
            self.logger.error(traceback.format_exc())
            return False

        return True
    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

        self.params = {
            k: [v]
            for k, v in (requests.compat.unquote(x).split('=') for x in [
                s2 for s1 in connection.query.split('&')
                for s2 in s1.split(';')
            ] if '=' in x)
        }
        # 15 minutes cache
        if not Torrenttelik.playlist or (
                int(time.time()) - Torrenttelik.playlisttime > 15 * 60):
            if not self.downloadPlaylist(config.url):
                connection.dieWithError()
                return

        add_ts = True if connection.path.endswith('/ts') else False
        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)
        Torrenttelik.logger.debug('Generating requested m3u playlist')

        try:
            for channel in Torrenttelik.playlist['channels']:
                channel['group'] = channel.get('cat', '')
                channel['url'] = 'acestream://%s' % channel.get('url', '')
                playlistgen.addItem(channel)
        except Exception as e:
            Torrenttelik.logger.error("Can't parse JSON! %s" % repr(e))
            return

        Torrenttelik.logger.debug('Exporting m3u playlist')
        exported = playlistgen.exportm3u(
            hostport,
            header=config.m3uheadertemplate,
            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 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
            else: origin = requests.get(config.url, headers=headers, timeout=5).text

            self.logger.info('TTV playlist ' + config.url + ' downloaded')
            self.playlisttime = int(time.time())
            self.playlist = PlaylistGenerator()
            self.channels = dict()
            m = hashlib.md5()
            pattern = re.compile(r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?')

            for match in pattern.finditer(origin.encode('UTF-8'), re.MULTILINE):
                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://', 'infohash://')) \
                      or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                    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)
                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: self.updatelogos = False # p2pproxy plugin seems not configured
        return True
Example #10
0
    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

        add_ts = True if connection.path.endswith('/ts') else False
        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)

        Allfon.logger.debug('Generating requested m3u playlist')

        pattern = re.compile(
            r',(?P<name>\S.+)[\r\n].+[\r\n].+[\r\n](?P<url>[^\r\n]+)?')
        for match in pattern.finditer(Allfon.playlist, re.MULTILINE):
            playlistgen.addItem(match.groupdict())

        Allfon.logger.debug('Exporting m3u playlist')
        params = {
            k: [v]
            for k, v in (requests.compat.unquote(x).split('=') for x in [
                s2 for s1 in connection.query.split('&')
                for s2 in s1.split(';')
            ] if '=' in x)
        }
        fmt = params['fmt'][0] if 'fmt' in params else None

        exported = playlistgen.exportm3u(hostport,
                                         header=config.m3uheadertemplate,
                                         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)
Example #11
0
def add_playlists(n):
    cursor, conn = open_connection()
    gen_playlist = PlaylistGenerator()
    data = gen_playlist.get_primary_key_data(n)
    for d in data:
        params = gen_playlist.get_params()
        print('id: ', d, params, sep=': ')
        cursor.execute(
            'insert into playlist (id, name, quantity, author, duration, icon_path) VALUES (%s, %s, %s, %s, %s, '
            '%s);commit;', (d, params.get('name'), params.get('quantity'),
                            params.get('author'), params.get('duration'),
                            params.get('icon_path')))
    print(n, "Playlists added", sep=' ')
    close_connection(cursor, conn)
    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(connection.path)
        params = parse_qs(url.query)
        fmt = params['fmt'][0] if 'fmt' in params 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, headers_only=False):

        hostport = connection.headers['Host']

        if headers_only:
            connection.send_response(200)
            connection.send_header('Content-Type',
                                   'audio/mpegurl; charset=utf-8')
            connection.send_header('Connection', 'close')
            connection.end_headers()
            return

        params = parse_qs(connection.query)
        # 15 minutes cache
        if not Torrenttelik.playlist or (
                int(time.time()) - Torrenttelik.playlisttime > 15 * 60):
            if not self.downloadPlaylist(config.url):
                connection.dieWithError()
                return

        add_ts = True if connection.path.endswith('/ts') else False
        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)
        Torrenttelik.logger.debug('Generating requested m3u playlist')

        try:
            for channel in Torrenttelik.playlist['channels']:
                channel['group'] = channel.get('cat', '')
                channel['url'] = 'acestream://%s' % channel.get('url', '')
                playlistgen.addItem(channel)
        except Exception as e:
            Torrenttelik.logger.error("Can't parse JSON! %s" % repr(e))
            return

        Torrenttelik.logger.debug('Exporting m3u playlist')
        exported = playlistgen.exportm3u(hostport,
                                         header=config.m3uheadertemplate,
                                         add_ts=add_ts,
                                         fmt=params.get(
                                             'fmt', [''])[0]).encode('utf-8')

        connection.send_response(200)
        connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8')
        connection.send_header('Access-Control-Allow-Origin', '*')
        connection.send_header('Content-Length', str(len(exported)))
        connection.send_header('Connection', 'close')
        connection.end_headers()

        connection.wfile.write(exported)
Example #14
0
    def handle(self, connection, headers_only=False):

        hostport = connection.headers['Host']
        if headers_only:
            connection.send_response(200)
            connection.send_header('Content-Type',
                                   'audio/mpegurl; charset=utf-8')
            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

        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)

        Allfon.logger.debug('Generating requested m3u playlist')

        pattern = re.compile(
            r',(?P<name>.+)[\r\n].+[\r\n].+[\r\n](?P<url>[^\r\n]+)?')
        for match in pattern.finditer(Allfon.playlist, re.MULTILINE):
            playlistgen.addItem(match.groupdict())

        Allfon.logger.debug('Exporting m3u playlist')
        params = parse_qs(connection.query)
        add_ts = True if connection.path.endswith('/ts') else False

        exported = playlistgen.exportm3u(hostport,
                                         header=config.m3uheadertemplate,
                                         add_ts=add_ts,
                                         fmt=params.get(
                                             'fmt', [''])[0]).encode('utf-8')

        connection.send_response(200)
        connection.send_header('Content-Type', 'audio/mpegurl; charset=utf-8')
        connection.send_header('Access-Control-Allow-Origin', '*')
        connection.send_header('Content-Length', str(len(exported)))
        connection.send_header('Connection', 'close')
        connection.end_headers()

        connection.wfile.write(exported)
Example #15
0
    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

        add_ts = True if connection.path.endswith('/ts') else False
        playlistgen = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)

        pattern = re.compile(
            r',(?P<name>\S.+)[\r\n].+[\r\n].+[\r\n](?P<url>[^\r\n]+)?')
        for match in pattern.finditer(Allfon.playlist, re.MULTILINE):
            playlistgen.addItem(match.groupdict())

        Allfon.logger.info('AllFon playlist created')
        params = parse_qs(connection.query)
        fmt = params['fmt'][0] if 'fmt' in params 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)
Example #16
0
    def handle(self, connection, headers_only=False):
        P2pproxy.logger.debug('Handling request')

        hostport = connection.headers['Host']
        self.params = parse_qs(connection.query)
        # /channels/ branch
        if connection.reqtype in ('channels', 'channels.m3u'):
            # /channels/play?id=[id]
            if len(
                    connection.splittedpath
            ) == 3 and connection.splittedpath[2].split('?')[0] == 'play':
                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(400,
                                                'Bad request')  # 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: '/url/' + requests.utils.quote(
                            match.group(0), '') + '/stream.mp4', stream)
                elif stream_type == 'contentid':
                    stream_url = re.sub(
                        '^([0-9a-f]{40})',
                        lambda match: '/content_id/' + requests.utils.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'))
            # /channels/?filter=[filter]&group=[group]&type=m3u
            elif connection.reqtype == 'channels.m3u' or self.get_param(
                    '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:
                        continue  # filter channels by group

                    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 deinterlace=1 m3uautoload=1 cache=1000\n' % (
                    config.tvgurl, config.tvgshift)
                exported = playlistgen.exportm3u(
                    hostport=hostport,
                    header=header,
                    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)
            # /channels/?filter=[filter]
            else:
                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)
        # same as /channels request
        elif connection.reqtype == 'xbmc.pvr':
            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)
        # /archive/ branch
        elif connection.reqtype == 'archive':
            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 'days' in self.params else 7
                suffix = '&suffix=' + self.get_param(
                    'suffix') if 'suffix' in self.params 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 'date' in self.params:
                    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 'days' in self.params 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 'suffix' in self.params 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
            # /archive/channels
            elif len(connection.splittedpath
                     ) == 3 and connection.splittedpath[2] == '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
            # /archive/play?id=[record_id]
            if len(
                    connection.splittedpath
            ) == 3 and connection.splittedpath[2].split('?')[0] == 'play':
                record_id = self.get_param('id')
                if not record_id:
                    connection.dieWithError(400, 'Bad request')  # 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: '/url/' + requests.utils.quote(
                            match.group(0), '') + '/stream.mp4', stream)
                elif stream_type == 'contentid':
                    stream_url = re.sub(
                        '^([0-9a-f]{40})',
                        lambda match: '/content_id/' + requests.utils.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'))
            # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel]
            elif self.get_param('type') == 'm3u':
                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 %s' % 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 = datetime.fromtimestamp(
                            float(
                                record.getAttribute('time'))).strftime('%H:%M')
                        n = '%s %s' % (d, 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')).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)
            # /archive/?date=[param_date]&channel_id=[param_channel]
            else:
                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:
                        connection.dieWithError(500,
                                                'Date param is not correct!',
                                                logging.ERROR)
                        return
                param_channel = self.get_param('channel_id')
                if param_channel == '' or not param_channel:
                    connection.dieWithError(
                        500,
                        'Got /archive/ request but no channel_id specified!',
                        logging.ERROR)
                    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)
        # Used to generate logomap for the torrenttv plugin
        elif connection.reqtype == 'logos':
            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):
        P2pproxy.logger.debug('Handling request')

        hostport = connection.headers['Host']
        self.params = parse_qs(connection.query)

        # /channels/ branch
        if connection.reqtype in ('channels', 'channels.m3u'):

            if connection.path.endswith('play'):  # /channels/play?id=[id]
                channel_id = self.params.get('id', [''])[0]
                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.params.get('_', [''])[0]:
                        P2pproxy.logger.debug('Status check')
                        response_headers = {
                            'Content-Type': 'text/plain;charset=utf-8',
                            'Server': 'P2pProxy/1.0.4.4 HTTPAceProxy',
                            'Access-Control-Allow-Origin': '*',
                            'Connection': 'close'
                        }
                        connection.send_response(200)
                        for k, v in response_headers.items():
                            connection.send_header(k, v)
                        connection.wfile.write('\r\n')
                        return
                    else:
                        connection.send_error(400,
                                              'Bad request')  # Bad request

                try:
                    stream_type, stream, translations_list = TorrentTvApi(
                        config.email,
                        config.password).stream_source(channel_id)
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)
                name = logo = ''

                for channel in translations_list:
                    if channel.getAttribute('id') == channel_id:
                        name = channel.getAttribute('name')
                        logo = channel.getAttribute('logo')
                        if logo != '' and config.fullpathlogo:
                            logo = config.logobase + logo
                        break

                if stream_type not in ('torrent', 'contentid'):
                    connection.send_error(
                        404, 'Unknown stream type: %s' % stream_type,
                        logging.ERROR)
                elif stream_type == 'torrent':
                    connection.path = '/url/%s/%s.ts' % (quote(stream,
                                                               ''), name)
                elif stream_type == 'contentid':
                    connection.path = '/content_id/%s/%s.ts' % (stream, name)

                connection.__dict__.update(
                    {'splittedpath': connection.path.split('/')})
                connection.__dict__.update({
                    'channelName':
                    name,
                    'channelIcon':
                    logo,
                    'reqtype':
                    connection.splittedpath[1].lower()
                })
                return

            # /channels/?filter=[filter]&group=[group]&type=m3u
            elif connection.reqtype == 'channels.m3u' or self.params.get(
                    'type', [''])[0] == 'm3u':

                param_group = self.params.get('group', [''])[0]
                if param_group and 'all' in param_group: param_group = None

                try:
                    translations_list = TorrentTvApi(
                        config.email, config.password).translations(
                            self.params.get('filter', ['all'])[0])
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)

                playlistgen = PlaylistGenerator(
                    m3uchanneltemplate=config.m3uchanneltemplate)
                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.split(','):
                        continue  # filter channels by &group=1,2,5...

                    name = channel.getAttribute('name')
                    group = TorrentTvApi.CATEGORIES[int(group_id)]
                    cid = channel.getAttribute('id')
                    logo = channel.getAttribute('logo')
                    if logo != '' and config.fullpathlogo:
                        logo = config.logobase + logo

                    fields = {
                        'name':
                        name,
                        'id':
                        cid,
                        'url':
                        cid,
                        'group':
                        group,
                        'logo':
                        logo,
                        'tvgid':
                        config.tvgid.format(**fields)
                        if channel.getAttribute('epg_id') != '0' else ''
                    }
                    playlistgen.addItem(fields)

                P2pproxy.logger.debug('Exporting m3u playlist')
                exported = playlistgen.exportm3u(
                    hostport=hostport,
                    header=config.m3uheadertemplate,
                    fmt=self.params.get('fmt', [''])[0])
                connection.send_response(200)
                connection.send_header('Content-Type',
                                       'audio/mpegurl; charset=utf-8')
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    exported = P2pproxy.compress_method[h].compress(
                        exported) + P2pproxy.compress_method[h].flush()
                    connection.send_header('Content-Encoding', h)
                except:
                    pass

                connection.send_header('Content-Length', len(exported))
                connection.end_headers()
                connection.wfile.write(exported)

            # /channels/?filter=[filter]
            else:
                try:
                    translations_list = TorrentTvApi(
                        config.email, config.password).translations(
                            self.params.get('filter', ['all'])[0], True)
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)

                P2pproxy.logger.debug('Exporting m3u playlist')
                response_headers = {
                    'Access-Control-Allow-Origin': '*',
                    'Connection': 'close',
                    'Content-Type': 'text/xml;charset=utf-8',
                    'Content-Length': len(translations_list)
                }
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    translations_list = P2pproxy.compress_method[h].compress(
                        translations_list) + P2pproxy.compress_method[h].flush(
                        )
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                response_headers['Content-Length'] = len(translations_list)
                connection.send_response(200)
                for k, v in response_headers.items():
                    connection.send_header(k, v)
                connection.end_headers()
                connection.wfile.write(translations_list)

        # same as /channels request
        elif connection.reqtype == 'xbmc.pvr' and connection.path.endswith(
                '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')

            try:
                translations_list = TorrentTvApi(config.email,
                                                 config.password).translations(
                                                     'all', True)
            except Exception as err:
                connection.send_error(404, '%s' % repr(err), logging.ERROR)
            try:
                h = connection.headers.get('Accept-Encoding').split(',')[0]
                translations_list = P2pproxy.compress_method[h].compress(
                    translations_list) + P2pproxy.compress_method[h].flush()
                connection.send_header('Content-Encoding', h)
            except:
                pass
            connection.send_header('Content-Length', len(translations_list))
            connection.end_headers()
            P2pproxy.logger.debug('Exporting m3u playlist')
            connection.wfile.write(translations_list)

        # /archive/ branch
        elif connection.reqtype == 'archive':
            if connection.path.endswith(
                ('dates', 'dates.m3u')):  # /archive/dates.m3u
                d = datetime.now()
                delta = timedelta(days=1)
                playlistgen = PlaylistGenerator()
                hostport = connection.headers['Host']
                days = int(self.params.get('days', ['7'])[0])
                suffix = '&suffix=%s' % self.params.get(
                    'suffix')[0] if 'suffix' in self.params 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 -= delta
                exported = playlistgen.exportm3u(hostport=hostport,
                                                 empty_header=True,
                                                 parse_url=False,
                                                 fmt=self.params.get(
                                                     'fmt', [''])[0])
                connection.send_response(200)
                connection.send_header('Content-Type',
                                       'audio/mpegurl; charset=utf-8')
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    exported = P2pproxy.compress_method[h].compress(
                        exported) + P2pproxy.compress_method[h].flush()
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                connection.send_header('Content-Length', len(exported))
                connection.end_headers()
                connection.wfile.write(exported)
                return

            elif connection.path.endswith(
                ('playlist', 'playlist.m3u')):  # /archive/playlist.m3u
                dates = []

                if 'date' in self.params:
                    for d in self.params['date']:
                        dates.append(self.parse_date(d).strftime('%d-%m-%Y'))
                else:
                    d = datetime.now()
                    delta = timedelta(days=1)
                    days = int(self.params.get('days', ['7'])[0])
                    for i in range(days):
                        dates.append(d.strftime('%d-%m-%Y'))
                        d -= delta

                connection.send_response(200)
                connection.send_header('Content-Type',
                                       'audio/mpegurl; charset=utf-8')

                try:
                    channels_list = TorrentTvApi(
                        config.email, config.password).archive_channels()
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)
                hostport = connection.headers['Host']
                playlistgen = PlaylistGenerator()
                suffix = '&suffix=%s' % self.params.get(
                    'suffix')[0] if 'suffix' in self.params 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 = config.logobase + 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=hostport,
                                                 empty_header=True,
                                                 parse_url=False,
                                                 fmt=self.params.get(
                                                     'fmt', [''])[0])
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    exported = P2pproxy.compress_method[h].compress(
                        exported) + P2pproxy.compress_method[h].flush()
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                connection.send_header('Content-Length', len(exported))
                connection.end_headers()
                connection.wfile.write(exported)
                return

            elif connection.path.endswith('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')

                try:
                    archive_channels = TorrentTvApi(
                        config.email, config.password).archive_channels(True)
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)
                P2pproxy.logger.debug('Exporting m3u playlist')
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    archive_channels = P2pproxy.compress_method[h].compress(
                        archive_channels) + P2pproxy.compress_method[h].flush(
                        )
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                connection.send_header('Content-Length', len(archive_channels))
                connection.end_headers()
                connection.wfile.write(archive_channels)
                return

            if connection.path.endswith(
                    'play'):  # /archive/play?id=[record_id]
                record_id = self.params.get('id', [''])[0]
                if not record_id:
                    connection.send_error(400, 'Bad request')  # Bad request

                try:
                    stream_type, stream = TorrentTvApi(
                        config.email,
                        config.password).archive_stream_source(record_id)
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)

                if stream_type not in ('torrent', 'contentid'):
                    connection.send_error(
                        404, 'Unknown stream type: %s' % stream_type,
                        logging.ERROR)
                elif stream_type == 'torrent':
                    connection.path = '/url/%s/stream.ts' % quote(stream, '')
                elif stream_type == 'contentid':
                    connection.path = '/content_id/%s/stream.ts' % stream

                connection.__dict__.update(
                    {'splittedpath': connection.path.split('/')})
                connection.__dict__.update(
                    {'reqtype': connection.splittedpath[1].lower()})
                return

            # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel]
            elif self.params.get('type', [''])[0] == 'm3u':

                playlistgen = PlaylistGenerator()
                param_channel = self.params.get('channel_id', [''])[0]
                d = self.get_date_param()

                if not param_channel:
                    try:
                        channels_list = TorrentTvApi(
                            config.email, config.password).archive_channels()
                    except Exception as err:
                        connection.send_error(404, '%s' % repr(err),
                                              logging.ERROR)

                    for channel in channels_list:
                        channel_id = channel.getAttribute('epg_id')
                        try:
                            try:
                                records_list = TorrentTvApi(
                                    config.email,
                                    config.password).records(channel_id, d)
                            except Exception as err:
                                connection.send_error(404, '%s' % repr(err),
                                                      logging.ERROR)
                            channel_name = channel.getAttribute('name')
                            logo = channel.getAttribute('logo')
                            if logo != '' and config.fullpathlogo:
                                logo = config.logobase + 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 %s' % channel_id)

                else:
                    try:
                        records_list = TorrentTvApi(config.email,
                                                    config.password).records(
                                                        param_channel, d)
                        channels_list = TorrentTvApi(
                            config.email, config.password).archive_channels()
                    except Exception as err:
                        connection.send_error(404, '%s' % repr(err),
                                              logging.ERROR)
                    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 = datetime.fromtimestamp(
                            float(
                                record.getAttribute('time'))).strftime('%H:%M')
                        n = '%s %s' % (d, 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 = config.logobase + logo

                        playlistgen.addItem({
                            'group': channel_name,
                            'name': n,
                            'url': record_id,
                            'logo': logo,
                            'tvg': ''
                        })

                P2pproxy.logger.debug('Exporting m3u playlist')
                exported = playlistgen.exportm3u(hostport=hostport,
                                                 empty_header=True,
                                                 archive=True,
                                                 fmt=self.params.get(
                                                     'fmt', [''])[0])

                connection.send_response(200)
                connection.send_header('Content-Type',
                                       'audio/mpegurl; charset=utf-8')
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    exported = P2pproxy.compress_method[h].compress(
                        exported) + P2pproxy.compress_method[h].flush()
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                connection.send_header('Content-Length', len(exported))
                connection.end_headers()
                connection.wfile.write(exported)

            # /archive/?date=[param_date]&channel_id=[param_channel]
            else:
                param_date = self.params.get('date', [''])[0]
                if not param_date: d = datetime.now()
                else:
                    try:
                        d = parse_date(param_date)
                    except:
                        return
                param_channel = self.params.get('channel_id', [''])[0]
                if not param_channel:
                    connection.send_error(
                        500,
                        'Got /archive/ request but no channel_id specified!',
                        logging.ERROR)

                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')

                try:
                    records_list = TorrentTvApi(config.email,
                                                config.password).records(
                                                    param_channel,
                                                    d.strftime('%d-%m-%Y'),
                                                    True)
                except Exception as err:
                    connection.send_error(404, '%s' % repr(err), logging.ERROR)
                P2pproxy.logger.debug('Exporting m3u playlist')
                try:
                    h = connection.headers.get('Accept-Encoding').split(',')[0]
                    records_list = P2pproxy.compress_method[h].compress(
                        records_list) + P2pproxy.compress_method[h].flush()
                    connection.send_header('Content-Encoding', h)
                except:
                    pass
                connection.send_header('Content-Length', len(records_list))
                connection.end_headers()
                connection.wfile.write(records_list)

        # Used to generate logomap for the torrenttv plugin
        elif connection.reqtype == 'logobase':
            logomap = {}
            try:
                import config.picons.torrenttv as picons
                logomap = {
                    k: v[v.rfind('/') + 1:]
                    for k, v in picons.logomap.items() if v is not None
                }
            except:
                pass

            #try: translations_list = TorrentTvApi(config.email, config.password).translations('all')
            #except Exception as err:
            #   connection.send_error(404, '%s' % repr(err), logging.ERROR)
            #   return
            #logomap.update({ channel.getAttribute('name'):channel.getAttribute('logo') for channel in translations_list })
            import requests
            url = 'http://hmxuku36whbypzxi.onion/trash/ttv-list/ttv_logo.json'
            proxies = {
                'http': 'socks5h://192.168.2.1:9100',
                'https': 'socks5h://192.168.2.1:9100'
            }
            with requests.get(url, proxies=proxies, timeout=30) as r:
                logomap.update(r.json())

            connection.send_response(200)
            if self.params.get('format', [''])[0] == 'json':
                from requests.compat import json
                exported = ensure_binary(
                    json.dumps(logomap, ensure_ascii=False))
                connection.send_header('Content-Type', 'application/json')
            else:
                exported = "logobase = '%s'\nlogomap = {\n" % config.logobase
                exported += ''.join("    u'%s': logobase + '%s',\n" %
                                    (name, logo)
                                    for name, logo in logomap.items())
                exported += '}\n'
                exported = ensure_binary(exported)
                connection.send_header('Content-Type',
                                       'text/plain;charset=utf-8')
            try:
                h = connection.headers.get('Accept-Encoding').split(',')[0]
                exported = P2pproxy.compress_method[h].compress(
                    exported) + P2pproxy.compress_method[h].flush()
                connection.send_header('Content-Encoding', h)
            except:
                pass
            connection.send_header('Content-Length', len(exported))
            connection.end_headers()
            connection.wfile.write(exported)
            P2pproxy.logger.debug('%s picon channels exported' % len(logomap))
Example #18
0
    def downloadPlaylist(self):
        self.playlisttime = int(gevent.time.time())
        self.playlist = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)
        self.channels = {}
        m = requests.auth.hashlib.md5()
        try:
            if self.updatelogos:
                try:
                    translations_list = TorrentTvApi(
                        p2pconfig.email,
                        p2pconfig.password).translations('all')
                    for channel in translations_list:
                        name = channel.getAttribute('name')
                        if channel.getAttribute('epg_id') not in ('0', '',
                                                                  ' '):
                            self.epg_id[name] = 'ttv%s' % channel.getAttribute(
                                'id')
                        if not name in self.logomap:
                            self.logomap[
                                name] = config.logobase + channel.getAttribute(
                                    'logo')

                    self.logger.debug('Logos updated')
                finally:
                    self.updatelogos = False  # p2pproxy plugin not configured

            headers = {'User-Agent': 'Magic Browser'}
            with requests.get(config.url,
                              headers=headers,
                              proxies=config.proxies,
                              stream=False,
                              timeout=30) as r:
                if r.encoding is None: r.encoding = 'utf-8'
                self.logger.info('TTV playlist %s downloaded' % config.url)
                pattern = requests.auth.re.compile(
                    r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?'
                )
                for match in pattern.finditer(r.text,
                                              requests.auth.re.MULTILINE):
                    itemdict = match.groupdict()
                    name = itemdict.get('name')

                    itemdict['logo'] = self.logomap.get(
                        name,
                        'http://static.acestream.net/sites/acestream/img/ACE-logo.png'
                    )
                    itemdict['tvgid'] = self.epg_id.get(name, '')

                    url = itemdict['url']
                    if url.startswith(('acestream://', 'infohash://')) \
                          or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                        self.channels[name] = url
                        itemdict['url'] = quote(name.encode('utf-8'),
                                                '') + '.ts'

                    self.playlist.addItem(itemdict)
                    m.update(name.encode('utf-8'))

                self.etag = '"' + m.hexdigest() + '"'
                self.logger.debug('Requested m3u playlist generated')

        except requests.exceptions.RequestException:
            self.logger.error("Can't download TTV playlist!")
            return False
        except:
            self.logger.error(traceback.format_exc())
            return False

        return True
Example #19
0
    def handle(self, connection, headers_only=False):
        P2pproxy.logger.debug('Handling request')

        hostport = connection.headers['Host']
        self.params = parse_qs(connection.query)

        # /channels/ branch
        if connection.reqtype in ('channels', 'channels.m3u'):

            if connection.path.endswith('play'):  # /channels/play?id=[id]
                channel_id = self.params.get('id', [''])[0]
                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.params.get('_', [''])[0]:
                        P2pproxy.logger.debug('Status check')
                        response_headers = {
                            'Content-Type': 'text/plain;charset=utf-8',
                            'Server': 'P2pProxy/1.0.4.4 HTTPAceProxy',
                            'Access-Control-Allow-Origin': '*',
                            'Connection': 'close'
                        }
                        connection.send_response(200)
                        for k, v in list(response_headers.items()):
                            connection.send_header(k, v)
                        connection.wfile.write('\r\n')
                        return
                    else:
                        connection.dieWithError(400,
                                                'Bad request')  # Bad request
                        return

                if headers_only:
                    connection.send_response(200)
                    connection.send_header('Content-Type', 'video/mpeg')
                    connection.end_headers()
                    return

                stream_type, stream, translations_list = TorrentTvApi(
                    config.email, config.password).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 logo != '' and config.fullpathlogo:
                            logo = P2pproxy.TTVU + logo
                        break

                if stream_type not in (b'torrent', b'contentid'):
                    connection.dieWithError(
                        404, 'Unknown stream type: %s' % stream_type,
                        logging.ERROR)
                    return
                elif stream_type == b'torrent':
                    connection.path = '/url/%s/stream.mp4' % quote(stream, '')
                elif stream_type == b'contentid':
                    connection.path = '/content_id/%s/stream.mp4' % stream

                connection.splittedpath = connection.path.split('/')
                connection.reqtype = connection.splittedpath[1].lower()
                connection.handleRequest(headers_only,
                                         name,
                                         logo,
                                         fmt=self.params.get('fmt', [''])[0])

            # /channels/?filter=[filter]&group=[group]&type=m3u
            elif connection.reqtype == 'channels.m3u' or self.params.get(
                    'type', [''])[0] == 'm3u':
                if headers_only:
                    connection.send_response(200)
                    connection.send_header('Content-Type',
                                           'audio/mpegurl; charset=utf-8')
                    connection.end_headers()
                    return

                param_group = self.params.get('group', [''])[0]
                if param_group and 'all' in param_group: param_group = None

                translations_list = TorrentTvApi(config.email,
                                                 config.password).translations(
                                                     self.params.get(
                                                         'filter', ['all'])[0])

                playlistgen = PlaylistGenerator(
                    m3uchanneltemplate=config.m3uchanneltemplate)
                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:
                        continue  # filter channels by &group=1,2,5...

                    name = channel.getAttribute('name')
                    group = TorrentTvApi.CATEGORIES[int(group_id)]
                    cid = channel.getAttribute('id')
                    logo = channel.getAttribute('logo')
                    if logo != '' and config.fullpathlogo:
                        logo = P2pproxy.TTVU + logo

                    fields = {
                        'name': name,
                        'id': cid,
                        'url': cid,
                        'group': group,
                        'logo': logo
                    }
                    if channel.getAttribute('epg_id') != '0':
                        fields['tvgid'] = config.tvgid % fields
                    playlistgen.addItem(fields)

                P2pproxy.logger.debug('Exporting m3u playlist')
                exported = playlistgen.exportm3u(
                    hostport=hostport,
                    header=config.m3uheadertemplate,
                    fmt=self.params.get('fmt', [''])[0]).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.end_headers()
                connection.wfile.write(exported)

            # /channels/?filter=[filter]
            else:
                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

                translations_list = TorrentTvApi(
                    config.email, config.password).translations(
                        self.params.get('filter', ['all'])[0], True)

                P2pproxy.logger.debug('Exporting m3u playlist')
                response_headers = {
                    'Access-Control-Allow-Origin': '*',
                    'Connection': 'close',
                    'Content-Type': 'text/xml;charset=utf-8',
                    'Content-Length': str(len(translations_list))
                }
                connection.send_response(200)
                for k, v in list(response_headers.items()):
                    connection.send_header(k, v)
                connection.end_headers()
                connection.wfile.write(translations_list)

        # same as /channels request
        elif connection.reqtype == 'xbmc.pvr' and connection.path.endswith(
                '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 = TorrentTvApi(config.email,
                                             config.password).translations(
                                                 'all', True)
            connection.send_header('Content-Length',
                                   str(len(translations_list)))
            connection.end_headers()
            P2pproxy.logger.debug('Exporting m3u playlist')
            connection.wfile.write(translations_list)

        # /archive/ branch
        elif connection.reqtype == 'archive':
            if connection.path.endswith(
                ('dates', 'dates.m3u')):  # /archive/dates.m3u
                d = datetime.now()
                delta = timedelta(days=1)
                playlistgen = PlaylistGenerator()
                hostport = connection.headers['Host']
                days = int(self.params.get('days', ['7'])[0])
                suffix = '&suffix=%s' % self.params.get('suffix', [''])[0]
                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 -= delta
                exported = playlistgen.exportm3u(hostport,
                                                 empty_header=True,
                                                 process_url=False,
                                                 fmt=self.params.get(
                                                     'fmt',
                                                     [''])[0]).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.end_headers()
                connection.wfile.write(exported)
                return

            elif connection.path.endswith(
                ('playlist', 'playlist.m3u')):  # /archive/playlist.m3u
                dates = list()

                if 'date' in self.params:
                    for d in self.params['date']:
                        dates.append(self.parse_date(d).strftime('%d-%m-%Y'))
                else:
                    d = datetime.now()
                    delta = timedelta(days=1)
                    days = int(self.params.get('days', ['7'])[0])
                    for i in range(days):
                        dates.append(d.strftime('%d-%m-%Y'))
                        d -= delta

                connection.send_response(200)
                connection.send_header('Content-Type',
                                       'audio/mpegurl; charset=utf-8')

                if headers_only:
                    connection.end_headers()
                    return

                channels_list = TorrentTvApi(
                    config.email, config.password).archive_channels()
                hostport = connection.headers['Host']
                playlistgen = PlaylistGenerator()
                suffix = '&suffix=%s' % self.params.get('suffix', [''])[0]

                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.params.get(
                                                     'fmt',
                                                     [''])[0]).encode('utf-8')
                connection.send_header('Content-Length', str(len(exported)))
                connection.end_headers()
                connection.wfile.write(exported)
                return

            elif connection.path.endswith('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 = TorrentTvApi(
                        config.email, config.password).archive_channels(True)
                    P2pproxy.logger.debug('Exporting m3u playlist')
                    connection.send_header('Content-Length',
                                           str(len(archive_channels)))
                    connection.end_headers()
                    connection.wfile.write(archive_channels)
                return

            if connection.path.endswith(
                    'play'):  # /archive/play?id=[record_id]
                record_id = self.params.get('id', [''])[0]
                if not record_id:
                    connection.dieWithError(400, 'Bad request')  # Bad request
                    return

                if headers_only:
                    connection.send_response(200)
                    connection.send_header("Content-Type", "video/mpeg")
                    connection.end_headers()
                    return

                stream_type, stream = TorrentTvApi(
                    config.email,
                    config.password).archive_stream_source(record_id)

                if stream_type not in (b'torrent', b'contentid'):
                    connection.dieWithError(
                        404, 'Unknown stream type: %s' % stream_type,
                        logging.ERROR)
                    return
                elif stream_type == b'torrent':
                    connection.path = '/url/%s/stream.mp4' % quote(stream, '')
                elif stream_type == b'contentid':
                    connection.path = '/content_id/%s/stream.mp4' % stream

                connection.splittedpath = connection.path.split('/')
                connection.reqtype = connection.splittedpath[1].lower()
                connection.handleRequest(headers_only,
                                         fmt=self.params.get('fmt', [''])[0])

            # /archive/?type=m3u&date=[param_date]&channel_id=[param_channel]
            elif self.params.get('type', [''])[0] == 'm3u':

                if headers_only:
                    connection.send_response(200)
                    connection.send_header('Content-Type',
                                           'audio/mpegurl; charset=utf-8')
                    connection.end_headers()
                    return

                playlistgen = PlaylistGenerator()
                param_channel = self.params.get('channel_id', [''])[0]
                d = self.get_date_param()

                if not param_channel:
                    channels_list = TorrentTvApi(
                        config.email, config.password).archive_channels()

                    for channel in channels_list:
                        channel_id = channel.getAttribute('epg_id')
                        try:
                            records_list = TorrentTvApi(
                                config.email,
                                config.password).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 %s' % channel_id)

                else:
                    records_list = TorrentTvApi(config.email,
                                                config.password).records(
                                                    param_channel, d)
                    channels_list = TorrentTvApi(
                        config.email, config.password).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 = datetime.fromtimestamp(
                            float(
                                record.getAttribute('time'))).strftime('%H:%M')
                        n = '%s %s' % (d, 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 m3u playlist')
                exported = playlistgen.exportm3u(hostport,
                                                 empty_header=True,
                                                 archive=True,
                                                 fmt=self.params.get(
                                                     'fmt',
                                                     [''])[0]).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.end_headers()
                connection.wfile.write(exported)

            # /archive/?date=[param_date]&channel_id=[param_channel]
            else:
                param_date = self.params.get('date', [''])[0]
                if not param_date: d = datetime.now()
                else:
                    try:
                        d = parse_date(param_date)
                    except:
                        return
                param_channel = self.params.get('channel_id', [''])[0]
                if not param_channel:
                    connection.dieWithError(
                        500,
                        'Got /archive/ request but no channel_id specified!',
                        logging.ERROR)
                    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 = TorrentTvApi(config.email,
                                                config.password).records(
                                                    param_channel,
                                                    d.strftime('%d-%m-%Y'),
                                                    True)
                    P2pproxy.logger.debug('Exporting m3u playlist')
                    connection.send_header('Content-Length',
                                           str(len(records_list)))
                    connection.end_headers()
                    connection.wfile.write(records_list)

        # Used to generate logomap for the torrenttv plugin
        elif connection.reqtype == 'logos':
            translations_list = TorrentTvApi(
                config.email, config.password).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))
                connection.wfile.write(
                    ",\n") if not channel == last else connection.wfile.write(
                        "\n")

            connection.wfile.write("}\n")
Example #20
0
class Torrenttv(AceProxyPlugin):

    # ttvplaylist handler is obsolete
    handlers = ('torrenttv', 'ttvplaylist')

    def __init__(self, AceConfig, AceProxy):
        self.logger = logging.getLogger('torrenttv_plugin')
        self.picons = self.channels = self.playlist = self.etag = None
        self.playlisttime = gevent.time.time()
        self.headers = {'User-Agent': 'Magic Browser'}
        if config.updateevery: gevent.spawn(self.playlistTimedDownloader)

    def playlistTimedDownloader(self):
        while 1:
            self.Playlistparser()
            gevent.sleep(config.updateevery * 60)

    def Playlistparser(self):
        try:
            s = requests.Session()
            s.mount('file://', FileAdapter())
            with s.get(config.url,
                       headers=self.headers,
                       proxies=config.proxies,
                       stream=False,
                       timeout=30) as r:
                if r.status_code != 304:
                    if r.encoding is None: r.encoding = 'utf-8'
                    self.headers['If-Modified-Since'] = gevent.time.strftime(
                        '%a, %d %b %Y %H:%M:%S %Z',
                        gevent.time.gmtime(self.playlisttime))
                    self.playlist = PlaylistGenerator(
                        m3uchanneltemplate=config.m3uchanneltemplate)
                    self.picons = picons.logomap
                    self.channels = {}
                    m = requests.auth.hashlib.md5()
                    self.logger.info('Playlist %s downloaded' % config.url)
                    pattern = requests.auth.re.compile(
                        r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?'
                    )
                    for match in pattern.finditer(r.text,
                                                  requests.auth.re.MULTILINE):
                        itemdict = match.groupdict()
                        name = itemdict.get('name', '')
                        if not 'logo' in itemdict:
                            itemdict['logo'] = picons.logomap.get(name)
                        self.picons[name] = itemdict['logo']

                        url = itemdict['url']
                        if url.startswith(('acestream://', 'infohash://')) \
                             or (url.startswith(('http://','https://')) and url.endswith(('.acelive', '.acestream', '.acemedia', '.torrent'))):
                            self.channels[name] = url
                            itemdict['url'] = quote(ensure_str('%s.ts' % name),
                                                    '')

                        self.playlist.addItem(itemdict)
                        m.update(name.encode('utf-8'))

                    self.etag = '"' + m.hexdigest() + '"'
                    self.logger.debug('torrenttv.m3u playlist generated')

                self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
            self.logger.error("Can't download %s playlist!" % config.url)
            return False
        except:
            self.logger.error(traceback.format_exc())
            return False

        return True

    def handle(self, connection, headers_only=False):
        play = False
        # 30 minutes cache
        if not self.playlist or (gevent.time.time() - self.playlisttime >
                                 30 * 60):
            if not self.Playlistparser():
                connection.dieWithError()
                return

        url = urlparse(connection.path)
        path = url.path[0:-1] if url.path.endswith('/') else url.path
        params = parse_qs(connection.query)

        if path.startswith('/%s/channel/' % connection.reqtype):
            if not path.endswith('.ts'):
                connection.dieWithError(404,
                                        'Invalid path: %s' % unquote(path),
                                        logging.ERROR)
                return
            name = ensure_text(unquote(path[path.rfind('/') + 1:]))
            url = self.channels.get('.'.join(name.split('.')[:-1]))
            if url is None:
                connection.dieWithError(404, 'Unknown channel: ' + name,
                                        logging.ERROR)
                return
            elif url.startswith('acestream://'):
                connection.path = '/content_id/%s/%s' % (url.split('/')[2],
                                                         name)
            elif url.startswith('infohash://'):
                connection.path = '/infohash/%s/%s' % (url.split('/')[2], name)
            elif url.startswith(('http://', 'https://')) and url.endswith(
                ('.acelive', '.acestream', '.acemedia', '.torrent')):
                connection.path = '/url/%s/%s' % (quote(url, ''), name)
            connection.splittedpath = connection.path.split('/')
            connection.reqtype = connection.splittedpath[1].lower()
            name = name.split('.')[0]
            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 not self.channels else '/%s/channel' % connection.reqtype
            add_ts = True if path.endswith('/ts') else False
            exported = self.playlist.exportm3u(hostport=hostport,
                                               path=path,
                                               add_ts=add_ts,
                                               header=config.m3uheadertemplate,
                                               fmt=params.get('fmt', [''])[0])
            response_headers = {
                'Content-Type': 'audio/mpegurl; charset=utf-8',
                'Connection': 'close',
                'Content-Length': len(exported),
                'Access-Control-Allow-Origin': '*',
                'ETag': self.etag
            }
            try:
                h = connection.headers.get('Accept-Encoding').split(',')[0]
                compress_method = {
                    'zlib': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS),
                    'deflate': zlib.compressobj(9, zlib.DEFLATED,
                                                -zlib.MAX_WBITS),
                    'gzip': zlib.compressobj(9, zlib.DEFLATED,
                                             zlib.MAX_WBITS | 16)
                }
                exported = compress_method[h].compress(
                    exported) + compress_method[h].flush()
                response_headers['Content-Length'] = len(exported)
                response_headers['Content-Encoding'] = h
            except:
                pass

            connection.send_response(200)
            gevent.joinall([
                gevent.spawn(connection.send_header, k, v)
                for (k, v) in response_headers.items()
            ])
            connection.end_headers()

        if play:
            connection.handleRequest(headers_only,
                                     name,
                                     self.picons.get(name),
                                     fmt=params.get('fmt', [''])[0])
        elif not headers_only:
            self.logger.debug('Exporting torrenttv.m3u playlist')
            connection.wfile.write(exported)
class Torrenttv(AceProxyPlugin):

    # ttvplaylist handler is obsolete
    handlers = (
        'torrenttv',
        'ttvplaylist',
    )

    def __init__(self, AceConfig, AceStuff):
        self.logger = logging.getLogger('torrenttv_plugin')
        self.channels = self.playlist = self.playlisttime = self.etag = self.tvgid = None
        self.logomap = config.logomap
        self.epg_id = {k: '' for k in self.logomap}
        self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe'

        if config.updateevery: gevent.spawn(self.playlistTimedDownloader)

    def playlistTimedDownloader(self):
        while 1:
            self.downloadPlaylist()
            gevent.sleep(config.updateevery * 60)

    def downloadPlaylist(self):
        self.playlisttime = int(gevent.time.time())
        self.playlist = PlaylistGenerator(
            m3uchanneltemplate=config.m3uchanneltemplate)
        self.channels = {}
        m = hashlib.md5()
        try:
            if self.updatelogos:
                try:
                    translations_list = TorrentTvApi(
                        p2pconfig.email,
                        p2pconfig.password).translations('all')
                    for channel in translations_list:
                        name = channel.getAttribute('name')
                        if channel.getAttribute('epg_id') not in ('0', '',
                                                                  ' '):
                            self.epg_id[name] = 'ttv%s' % channel.getAttribute(
                                'id')
                        if not name in self.logomap:
                            self.logomap[
                                name] = config.logobase + channel.getAttribute(
                                    'logo')

                    self.logger.debug("Logos updated")
                    self.updatelogos = False
                except:
                    self.updatelogos = False  # p2pproxy plugin seems not configured

            headers = {'User-Agent': 'Magic Browser'}
            with requests.get(config.url,
                              headers=headers,
                              proxies=config.proxies,
                              stream=False,
                              timeout=30) as r:
                if r.encoding is None: r.encoding = 'utf-8'
                self.logger.info('TTV playlist %s downloaded' % config.url)
                pattern = re.compile(
                    r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?'
                )
                for match in pattern.finditer(r.text, re.MULTILINE):
                    itemdict = match.groupdict()
                    name = itemdict.get('name')

                    itemdict['logo'] = self.logomap.get(
                        name,
                        'http://static.acestream.net/sites/acestream/img/ACE-logo.png'
                    )
                    itemdict['tvgid'] = self.epg_id.get(name, '')

                    url = itemdict['url']
                    if url.startswith(('acestream://', 'infohash://')) \
                          or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                        self.channels[name] = url
                        itemdict['url'] = requests.compat.quote(
                            name.encode('utf-8'), '') + '.ts'

                    self.playlist.addItem(itemdict)
                    m.update(name.encode('utf-8'))

                self.etag = '"' + m.hexdigest() + '"'
                self.logger.debug('Requested m3u playlist generated')

        except requests.exceptions.ConnectionError:
            self.logger.error("Can't download TTV playlist!")
            return False
        except:
            self.logger.error(traceback.format_exc())
            return False

        return True

    def handle(self, connection, headers_only=False):
        play = False
        # 30 minutes cache
        if not self.playlist or (int(gevent.time.time()) - self.playlisttime >
                                 30 * 60):
            self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe'
            if not self.downloadPlaylist():
                connection.dieWithError()
                return

        url = requests.compat.urlparse(connection.path)
        path = url.path[0:-1] if url.path.endswith('/') else url.path
        params = parse_qs(connection.query)

        if path.startswith('/torrenttv/channel/'):
            if not path.endswith('.ts'):
                connection.dieWithError(
                    404, 'Invalid path: %s' % requests.compat.unquote(path),
                    logging.ERROR)
                return
            try:
                name = requests.compat.unquote(path.rsplit(
                    '/', 1)[1][:-3]).decode('utf-8')
            except AttributeError:
                name = requests.compat.unquote(path.rsplit('/', 1)[1][:-3])
            url = self.channels.get(name, None)
            if url is None:
                connection.dieWithError(404, 'Unknown channel: ' + name,
                                        logging.ERROR)
                return
            elif url.startswith('acestream://'):
                connection.path = '/content_id/%s/stream.ts' % url.split(
                    '/')[2]
            elif url.startswith('infohash://'):
                connection.path = '/infohash/%s/stream.ts' % url.split('/')[2]
            elif url.startswith(('http://', 'https://')) and url.endswith(
                ('.acelive', '.acestream', '.acemedia')):
                connection.path = '/url/%s/stream.ts' % requests.compat.quote(
                    url, '')
            connection.splittedpath = connection.path.split('/')
            connection.reqtype = connection.splittedpath[1].lower()
            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:
            self.logger.debug('Exporting m3u playlist')
            hostport = connection.headers['Host']
            path = '' if len(self.channels) == 0 else '/torrenttv/channel'
            add_ts = True if path.endswith('/ts') else False
            exported = self.playlist.exportm3u(
                hostport=hostport,
                path=path,
                add_ts=add_ts,
                header=config.m3uheadertemplate,
                fmt=params.get('fmt', [''])[0]).encode('utf-8')

            response_headers = {
                'Content-Type': 'audio/mpegurl; charset=utf-8',
                'Access-Control-Allow-Origin': '*',
                'ETag': self.etag,
                'Content-Length': str(len(exported)),
                'Connection': 'close'
            }
            connection.send_response(200)
            for k, v in list(response_headers.items()):
                connection.send_header(k, v)
            connection.end_headers()

        if play:
            connection.handleRequest(headers_only,
                                     name,
                                     config.logomap.get(name),
                                     fmt=params.get('fmt', [''])[0])
        elif not headers_only:
            connection.wfile.write(exported)
Example #22
0
class Torrenttv(object):

    # ttvplaylist handler is obsolete
    handlers = ('torrenttv', 'ttvplaylist')

    def __init__(self, AceConfig, AceProxy):
        self.picons = self.channels = self.playlist = self.etag = None
        self.playlisttime = gevent.time.time()
        self.headers = {'User-Agent': 'Magic Browser'}
        if config.updateevery: schedule(config.updateevery * 60, self.Playlistparser)

    def Playlistparser(self):
        try:
           s = requests.Session()
           s.mount('file://', FileAdapter())
           with s.get(config.url, headers=self.headers, proxies=config.proxies, stream=False, timeout=30) as r:
              if r.status_code != 304:
                 if r.encoding is None: r.encoding = 'utf-8'
                 self.headers['If-Modified-Since'] = gevent.time.strftime('%a, %d %b %Y %H:%M:%S %Z', gevent.time.gmtime(self.playlisttime))
                 self.playlist = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate)
                 self.picons = picons.logomap
                 self.channels = {}
                 m = requests.auth.hashlib.md5()
                 logging.info('[%s]: playlist %s downloaded' % (self.__class__.__name__, config.url))
                 pattern = requests.utils.re.compile(r',(?P<name>.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?')
                 urlpattern = requests.utils.re.compile(r'^(acestream|infohash)://[0-9a-f]{40}$|^(http|https)://.*.(acelive|acestream|acemedia|torrent)$')
                 for match in pattern.finditer(r.text, requests.auth.re.MULTILINE):
                    itemdict = match.groupdict()
                    name = itemdict.get('name', '')
                    itemdict['logo'] = self.picons[name] = itemdict.get('logo', picons.logomap.get(name))
                    url = itemdict['url']

                    if requests.utils.re.search(urlpattern, url):
                       self.channels[name] = url
                       itemdict['url'] = quote(ensure_str(name), '')

                    self.playlist.addItem(itemdict)
                    m.update(ensure_binary(name))

                 self.etag = '"' + m.hexdigest() + '"'
                 logging.debug('[%s]: plugin playlist generated' % self.__class__.__name__)

              self.playlisttime = gevent.time.time()

        except requests.exceptions.RequestException:
           logging.error("[%s]: can't download %s playlist!" % (self.__class__.__name__, config.url))
           logging.error(traceback.format_exc())
           return False
        except: logging.error(traceback.format_exc()); return False

        return True

    def handle(self, connection):
        # 30 minutes cache
        if not self.playlist or (gevent.time.time() - self.playlisttime > 30 * 60):
           if not self.Playlistparser(): connection.send_error()

        connection.ext = query_get(connection.query, 'ext', 'ts')
        if connection.path.startswith('/{reqtype}/channel/'.format(**connection.__dict__)):
           if not connection.path.endswith(connection.ext):
              connection.send_error(404, 'Invalid path: {path}'.format(**connection.__dict__), logging.ERROR)
           name = ensure_text(unquote(os.path.splitext(os.path.basename(connection.path))[0]))
           url = self.channels.get(name)
           if url is None:
              connection.send_error(404, '[%s]: unknown channel: %s' % (self.__class__.__name__, name), logging.ERROR)
           connection.__dict__.update({'channelName': name,
                                       'channelIcon': self.picons.get(name),
                                       'path': {'acestream': '/content_id/%s/%s.%s' % (urlparse(url).netloc, name, connection.ext),
                                                'infohash' : '/infohash/%s/%s.%s' % (urlparse(url).netloc, name, connection.ext),
                                                'http'     : '/url/%s/%s.%s' % (quote(url,''), name, connection.ext),
                                                'https'    : '/url/%s/%s.%s' % (quote(url,''), name, connection.ext),
                                               }[urlparse(url).scheme]})
           connection.__dict__.update({'splittedpath': connection.path.split('/')})
           connection.__dict__.update({'reqtype': connection.splittedpath[1].lower()})
           return

        elif self.etag == connection.headers.get('If-None-Match'):
           logging.debug('[%s]: ETag matches. Return 304 to [%s]' % (self.__class__.__name__, connection.clientip))
           connection.send_response(304)
           connection.send_header('Connection', 'close')
           connection.end_headers()
           return

        else:
           exported = self.playlist.exportm3u( hostport=connection.headers['Host'],
                                               path='' if not self.channels else '/{reqtype}/channel'.format(**connection.__dict__),
                                               header=config.m3uheadertemplate,
                                               query=connection.query
                                              )
           response_headers = {'Content-Type': 'audio/mpegurl; charset=utf-8', 'Connection': 'close', 'Access-Control-Allow-Origin': '*'}
           try:
              h = connection.headers.get('Accept-Encoding').split(',')[0]
              compress_method = { 'zlib': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS),
                                  'deflate': zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS),
                                  'gzip': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) }
              exported = compress_method[h].compress(exported) + compress_method[h].flush()
              response_headers['Content-Encoding'] = h
           except: pass
           response_headers['Content-Length'] = len(exported)
           if connection.request_version == 'HTTP/1.1':
              response_headers['ETag'] = self.etag
           connection.send_response(200)
           gevent.joinall([gevent.spawn(connection.send_header, k, v) for (k,v) in response_headers.items()])
           connection.end_headers()
           connection.wfile.write(exported)
           logging.debug('[%s]: plugin sent playlist to [%s]' % (self.__class__.__name__, connection.clientip))
Example #23
0
    def Playlistparser(self):
        try:
           s = requests.Session()
           s.mount('file://', FileAdapter())
           for index in range(3):
               try:
                   logging.info("[%s]: get: %s" % (self.__class__.__name__, config.url))
                   with s.get(config.url, headers=self.headers, proxies=config.proxies, stream=False, timeout=(5,30)) as playlist:
                      if playlist.status_code != 304:
                         if playlist.encoding is None: playlist.encoding = 'utf-8'
                         playlist = playlist.json()
                         self.headers['If-Modified-Since'] = gevent.time.strftime('%a, %d %b %Y %H:%M:%S %Z', gevent.time.gmtime(self.playlisttime))
                         self.playlist = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate)
                         self.picons = picons.logomap
                         self.channels = {}
                         m = requests.auth.hashlib.md5()
                         logging.info('[%s]: playlist %s downloaded' % (self.__class__.__name__, config.url))
                         try:
                            for item in playlist:
                                channel = {}
                                name = item['name']
                                channel['name'] = name
                                channel['url'] = 'infohash://{}'.format(item['infohash'])
                                if 'categories' in item:
                                    channel['group'] = item['categories'][0]
                                else:
                                    channel['group'] = u'tv'
                                    print('No category: ', item)
                                channel['logo'] = self.picons[name] = channel.get('logo', get_logo(picons.logomap, name))
                                channel['availability'] = item['availability']
                                print("Added: ", channel)
                                self.playlist.addItem(channel)
                                m.update(ensure_binary(name))

                            #urlpattern = requests.utils.re.compile(r'^(acestream|infohash)://[0-9a-f]{40}$|^(http|https)://.*.(acelive|acestream|acemedia|torrent)$')
                            #for channel in playlist['channels']:
                            #   name = channel['name']
                            #   url = 'acestream://{url}'.format(**channel)
                            #   channel['group'] = channel.pop('cat')
                            #   channel['logo'] = self.picons[name] = channel.get('logo', get_logo(picons.logomap, name))
                            #
                            #   if requests.utils.re.search(urlpattern, url):
                            #      self.channels[name] = url
                            #      channel['url'] = quote(ensure_str(name),'')
                            #
                            #   self.playlist.addItem(channel)
                            #   m.update(ensure_binary(name))

                         except Exception as e:
                            print("Exception1: ", e)
                            logging.error("[%s]: can't parse JSON! %s" % (self.__class__.__name__, repr(e)))
                            return False

                         self.etag = '"' + m.hexdigest() + '"'
                         logging.debug('[%s]: plugin playlist generated' % self.__class__.__name__)

                      self.playlisttime = gevent.time.time()
                      logging.info("Return True")
                      print("Return True")
                      return True
               except ValueError as e:
                   print("Exception2: ", e)
                   logging.error("[%s]: can't parse %s playlist, attempt: %d" % (self.__class__.__name__, config.url, index + 1))
                   if index + 1 < 3:
                       logging.error("Sleeping")
                       time.sleep((index + 1) * 2)
                       logging.error("Sleeping end")
                   else:
                       logging.error("Return False")
                       return False

        except requests.exceptions.RequestException:
           logging.error("[%s]: can't download %s playlist!" % (self.__class__.__name__, config.url))
           return False
        except:
            logging.error("[%s]: can't parse %s playlist!" % (self.__class__.__name__, config.url))
            logging.error(traceback.format_exc())
            return False
Example #24
0
class Torrentsearch(object):

    handlers = ('ttv2',)

    def __init__(self, AceConfig, AceProxy):
        self.AceConfig = AceConfig
        self.picons = self.channels = self.playlist = self.etag = self.last_modified = None
        self.playlisttime = gevent.time.time()
        self.headers = {'User-Agent': 'Magic Browser'}
        if config.updateevery: schedule(config.updateevery * 60, self.Playlistparser)

    def Playlistparser(self):
        try:
           s = requests.Session()
           s.mount('file://', FileAdapter())
           for index in range(3):
               try:
                   logging.info("[%s]: get: %s" % (self.__class__.__name__, config.url))
                   with s.get(config.url, headers=self.headers, proxies=config.proxies, stream=False, timeout=(5,30)) as playlist:
                      if playlist.status_code != 304:
                         if playlist.encoding is None: playlist.encoding = 'utf-8'
                         playlist = playlist.json()
                         self.headers['If-Modified-Since'] = gevent.time.strftime('%a, %d %b %Y %H:%M:%S %Z', gevent.time.gmtime(self.playlisttime))
                         self.playlist = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate)
                         self.picons = picons.logomap
                         self.channels = {}
                         m = requests.auth.hashlib.md5()
                         logging.info('[%s]: playlist %s downloaded' % (self.__class__.__name__, config.url))
                         try:
                            for item in playlist:
                                channel = {}
                                name = item['name']
                                channel['name'] = name
                                channel['url'] = 'infohash://{}'.format(item['infohash'])
                                if 'categories' in item:
                                    channel['group'] = item['categories'][0]
                                else:
                                    channel['group'] = u'tv'
                                    print('No category: ', item)
                                channel['logo'] = self.picons[name] = channel.get('logo', get_logo(picons.logomap, name))
                                channel['availability'] = item['availability']
                                print("Added: ", channel)
                                self.playlist.addItem(channel)
                                m.update(ensure_binary(name))

                            #urlpattern = requests.utils.re.compile(r'^(acestream|infohash)://[0-9a-f]{40}$|^(http|https)://.*.(acelive|acestream|acemedia|torrent)$')
                            #for channel in playlist['channels']:
                            #   name = channel['name']
                            #   url = 'acestream://{url}'.format(**channel)
                            #   channel['group'] = channel.pop('cat')
                            #   channel['logo'] = self.picons[name] = channel.get('logo', get_logo(picons.logomap, name))
                            #
                            #   if requests.utils.re.search(urlpattern, url):
                            #      self.channels[name] = url
                            #      channel['url'] = quote(ensure_str(name),'')
                            #
                            #   self.playlist.addItem(channel)
                            #   m.update(ensure_binary(name))

                         except Exception as e:
                            print("Exception1: ", e)
                            logging.error("[%s]: can't parse JSON! %s" % (self.__class__.__name__, repr(e)))
                            return False

                         self.etag = '"' + m.hexdigest() + '"'
                         logging.debug('[%s]: plugin playlist generated' % self.__class__.__name__)

                      self.playlisttime = gevent.time.time()
                      logging.info("Return True")
                      print("Return True")
                      return True
               except ValueError as e:
                   print("Exception2: ", e)
                   logging.error("[%s]: can't parse %s playlist, attempt: %d" % (self.__class__.__name__, config.url, index + 1))
                   if index + 1 < 3:
                       logging.error("Sleeping")
                       time.sleep((index + 1) * 2)
                       logging.error("Sleeping end")
                   else:
                       logging.error("Return False")
                       return False

        except requests.exceptions.RequestException:
           logging.error("[%s]: can't download %s playlist!" % (self.__class__.__name__, config.url))
           return False
        except:
            logging.error("[%s]: can't parse %s playlist!" % (self.__class__.__name__, config.url))
            logging.error(traceback.format_exc())
            return False

    def handle(self, connection):
        # 30 minutes cache
        if not self.playlist or (gevent.time.time() - self.playlisttime > 30 * 60):
           if not self.Playlistparser():
              logging.info('Parser failed to parse')
              connection.send_error()

        connection.ext = query_get(connection.query, 'ext', 'ts')
        if connection.path.startswith('/{reqtype}/channel/'.format(**connection.__dict__)):
           if not connection.path.endswith(connection.ext):
              logging.info('Invalid path')
              connection.send_error(404, 'Invalid path: {path}'.format(**connection.__dict__), logging.ERROR)
           name = ensure_text(unquote(os.path.splitext(os.path.basename(connection.path))[0]))
           url = self.channels.get(name)
           if url is None:
              logging.info('Unknown channel')
              connection.send_error(404, '[%s]: unknown channel: %s' % (self.__class__.__name__, name), logging.ERROR)
           connection.__dict__.update({'channelName': name,
                                       'channelIcon': self.picons.get(name),
                                       'path': {'acestream': '/content_id/%s/%s.%s' % (urlparse(url).netloc, name, connection.ext),
                                                'infohash' : '/infohash/%s/%s.%s' % (urlparse(url).netloc, name, connection.ext),
                                                'http'     : '/url/%s/%s.%s' % (quote(url,''), name, connection.ext),
                                                'https'    : '/url/%s/%s.%s' % (quote(url,''), name, connection.ext),
                                               }[urlparse(url).scheme]})
           connection.__dict__.update({'splittedpath': connection.path.split('/')})
           connection.__dict__.update({'reqtype': connection.splittedpath[1].lower()})
           return

        elif self.etag == connection.headers.get('If-None-Match'):
           logging.debug('[%s]: ETag matches. Return 304 to [%s]' % (self.__class__.__name__, connection.clientip))
           connection.send_response(304)
           connection.send_header('Connection', 'close')
           connection.end_headers()
           return

        else:
           host_port = connection.headers['Host']
           exported = self.playlist.exportm3u( hostport=host_port,
                                               path='' if not self.channels else '/{reqtype}/channel'.format(**connection.__dict__),
                                               header=config.m3uheadertemplate.format(get_epg_url(host_port, config, config.tvgurl), config.tvgshift),
                                               query=connection.query
                                              )
           response_headers = {'Content-Type': 'audio/mpegurl; charset=utf-8', 'Connection': 'close', 'Access-Control-Allow-Origin': '*'}
           try:
              h = connection.headers.get('Accept-Encoding').split(',')[0]
              compress_method = { 'zlib': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS),
                                  'deflate': zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS),
                                  'gzip': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) }
              exported = compress_method[h].compress(exported) + compress_method[h].flush()
              response_headers['Content-Encoding'] = h
           except: pass
           response_headers['Content-Length'] = len(exported)
           if connection.request_version == 'HTTP/1.1':
              response_headers['ETag'] = self.etag
           connection.send_response(200)
           gevent.joinall([gevent.spawn(connection.send_header, k, v) for (k,v) in response_headers.items()])
           connection.end_headers()
           connection.wfile.write(exported)
           logging.debug('[%s]: plugin sent playlist to [%s]' % (self.__class__.__name__, connection.clientip))
Example #25
0
class Torrenttelik(AceProxyPlugin):

    handlers = ('torrent-telik',)

    def __init__(self, AceConfig, AceProxy):
        self.logger = logging.getLogger('torrenttelik_plugin')
        self.picons = self.channels = self.playlist = self.etag = self.last_modified = None
        self.playlisttime = gevent.time.time()
        self.headers = {'User-Agent': 'Magic Browser'}
        if config.updateevery: gevent.spawn(self.playlistTimedDownloader)

    def playlistTimedDownloader(self):
        while 1:
            self.Playlistparser()
            gevent.sleep(config.updateevery * 60)

    def Playlistparser(self):
        try:
           s = requests.Session()
           s.mount('file://', FileAdapter())
           with s.get(config.url, headers=self.headers, proxies=config.proxies, stream=False, timeout=30) as playlist:
              if playlist.status_code != 304:
                 if playlist.encoding is None: playlist.encoding = 'utf-8'
                 playlist = playlist.json()
                 self.headers['If-Modified-Since'] = gevent.time.strftime('%a, %d %b %Y %H:%M:%S %Z', gevent.time.gmtime(self.playlisttime))
                 self.playlist = PlaylistGenerator(m3uchanneltemplate=config.m3uchanneltemplate)
                 self.picons = picons.logomap
                 self.channels = {}
                 m = requests.auth.hashlib.md5()
                 self.logger.info('Playlist %s downloaded' % config.url)
                 try:
                    for channel in playlist['channels']:
                       name = channel['name']
                       url = 'acestream://{url}'.format(**channel)
                       channel['group'] = channel.pop('cat')
                       if not 'logo' in channel: channel['logo'] = picons.logomap.get(name)
                       self.picons[name] = channel['logo']

                       if url.startswith(('acestream://', 'infohash://')) \
                            or (url.startswith(('http://','https://')) and url.endswith(('.acelive', '.acestream', '.acemedia', '.torrent'))):
                          self.channels[name] = url
                          channel['url'] = quote(ensure_str(name),'')

                       self.playlist.addItem(channel)
                       m.update(name.encode('utf-8'))

                 except Exception as e:
                    self.logger.error("Can't parse JSON! %s" % repr(e))
                    return False

                 self.etag = '"' + m.hexdigest() + '"'
                 self.logger.debug('torrent-telik.m3u playlist generated')

              self.playlisttime = gevent.time.time()

        except: self.logger.error("Can't download %s playlist or received json is broken!" % config.url); return False

        return True

    def handle(self, connection, headers_only=False):
        play = False
        # 30 minutes cache
        if not self.playlist or (gevent.time.time() - self.playlisttime > 30 * 60):
           if not self.Playlistparser(): connection.dieWithError(); return

        url = urlparse(connection.path)
        path = url.path[0:-1] if url.path.endswith('/') else url.path
        ext = parse_qs(connection.query).get('ext', ['ts'])[0]
        if path.startswith('/%s/channel/' % connection.reqtype):
           if not path.endswith(ext):
              connection.dieWithError(404, 'Invalid path: %s' % unquote(path), logging.ERROR)
              return
           name = ensure_text(unquote(os.path.splitext(os.path.basename(path))[0]))
           url = self.channels.get(name)
           if url is None:
              connection.dieWithError(404, 'Unknown channel: %s' % name, logging.ERROR)
              return
           params = {'name': name, 'value': url.split('/')[2], 'ext': ext}
           if url.startswith('acestream://'):
              connection.path = u'/content_id/{value}/{name}.{ext}'.format(**params)
           elif url.startswith('infohash://'):
              connection.path = u'/infohash/{value}/{name}.{ext}'.format(**params)
           elif url.startswith(('http://', 'https://')) and url.endswith(('.acelive', '.acestream', '.acemedia', '.torrent')):
              params.update({'value': quote(url,'')})
              connection.path = u'/url/{value}/{name}.{ext}'.format(**params)
           connection.splittedpath = connection.path.split('/')
           connection.reqtype = connection.splittedpath[1].lower()
           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 not self.channels else '/%s/channel' % connection.reqtype
           exported = self.playlist.exportm3u(hostport=hostport, path=path, header=config.m3uheadertemplate, query=connection.query)
           response_headers = { 'Content-Type': 'audio/mpegurl; charset=utf-8', 'Connection': 'close', 'Content-Length': len(exported),
                                'Access-Control-Allow-Origin': '*', 'ETag': self.etag }
           try:
              h = connection.headers.get('Accept-Encoding').split(',')[0]
              compress_method = { 'zlib': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS),
                                  'deflate': zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS),
                                  'gzip': zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) }
              exported = compress_method[h].compress(exported) + compress_method[h].flush()
              response_headers['Content-Length'] = len(exported)
              response_headers['Content-Encoding'] = h
           except: pass

           connection.send_response(200)
           gevent.joinall([gevent.spawn(connection.send_header, k, v) for (k,v) in response_headers.items()])
           connection.end_headers()

        if play: connection.handleRequest(headers_only=headers_only, channelName=name, channelIcon=self.picons.get(name))
        elif not headers_only:
           self.logger.debug('Exporting torrent-telik.m3u playlist')
           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:
            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
            else: origin = requests.get(config.url, headers=headers, timeout=5).text

            self.logger.info('TTV playlist ' + config.url + ' downloaded')
            self.playlisttime = int(time.time())
            self.playlist = PlaylistGenerator()
            self.channels = dict()
            m = hashlib.md5()
            pattern = re.compile(r',(?P<name>\S.+) \((?P<group>.+)\)[\r\n]+(?P<url>[^\r\n]+)?')

            for match in pattern.finditer(origin.encode('UTF-8'), re.MULTILINE):
                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://', 'infohash://')) \
                      or (url.startswith(('http://','https://')) and url.endswith(('.acelive','.acestream','.acemedia'))):
                    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)
                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: self.updatelogos = False # p2pproxy plugin seems not configured
        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):
                self.updatelogos = p2pconfig.email != 're.place@me' and p2pconfig.password != 'ReplaceMe'
                if not self.downloadPlaylist():
                    connection.dieWithError()
                    return

            url = urlparse(connection.path)
            path = url.path[0:-1] if url.path.endswith('/') else url.path
            params = parse_qs(url.query)
            fmt = params['fmt'][0] if 'fmt' in params else None

            if path.startswith('/torrenttv/channel/'):
                if not path.endswith('.mp4'):
                    connection.dieWithError(404, 'Invalid path: ' + path, logging.ERROR)
                    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.ERROR)
                    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://', 'https://')) and url.endswith(('.torrent', '.acelive','.acestream', '.acemedia')):
                    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)