示例#1
0
    def handle(self, connection):
        path_file_ext = connection.path[connection.path.rfind('.') + 1:]
        if connection.splittedpath[
                1] == 'stat' and connection.splittedpath.__len__() == 2:
            if query_get(connection.query, 'action') == 'get_status':
                Stat.SendResponse(
                    200, 'json',
                    ensure_binary(
                        json.dumps(self.getStatusJSON(), ensure_ascii=True)),
                    connection)
            else:
                try:
                    Stat.SendResponse(200, 'html',
                                      Stat.getReqFileContent('index.html'),
                                      connection)
                except:
                    connection.send_error(404, 'Not Found')

        elif path_file_ext:
            try:
                Stat.SendResponse(
                    200, path_file_ext,
                    Stat.getReqFileContent(
                        connection.path.replace(r'/stat', '')), connection)
            except:
                connection.send_error(404, 'Not Found')
        else:
            connection.send_error(404, 'Not Found')
示例#2
0
    def exportm3u(self, **params):
        '''
        Exports m3u playlist
        params: hostport= '', path='', empty_header=False, archive=False, parse_url=True, header=None, query=None
        '''
        def line_generator(item):
            '''
            Generates EXTINF line with url
            '''
            item = item.copy() # {'group': XXX, 'tvg': XXX, 'logo': XXX, 'name': XXX, 'tvgid': XXX, 'url': XXX}
            params.update({'name': quote(ensure_str(item.get('name').replace('"', "'").replace(',', '.')), '')})
            url = item['url']
            if not params.get('parse_url'):
               if params.get('path') and params.get('path').endswith('channel'): # For plugins channel name maping
                  params.update({'value': url})
                  item['url'] = urlunparse(u'{schema};{netloc};{path}/{value}.{ext};;{query};'.format(**params).split(';'))
               elif url.startswith(('http://', 'https://')) and url.endswith(('.acelive', '.acestream', '.acemedia', '.torrent')): # For .acelive and .torrent
                  params.update({'value': quote(url,'')})
                  item['url'] = urlunparse(u'{schema};{netloc};/url/{value}/{name}.{ext};;{query};'.format(**params).split(';'))
               elif url.startswith('infohash://'): # For INFOHASHes
                  params.update({'value': url.split('/')[2]})
                  item['url'] = urlunparse(u'{schema};{netloc};/infohash/{value}/{name}.{ext};;{query};'.format(**params).split(';'))
               elif url.startswith('acestream://'): # For PIDs
                  params.update({'value': url.split('/')[2]})
                  item['url'] = urlunparse(u'{schema};{netloc};/content_id/{value}/{name}.{ext};;{query};'.format(**params).split(';'))
               elif params.get('archive') and url.isdigit(): # For archive channel id's
                  params.update({'value': url})
                  item['url'] = urlunparse(u'{schema};{netloc};/archive/play;;id={value};'.format(**params).split(';'))
               elif not params.get('archive') and url.isdigit(): # For channel id's
                  params.update({'value': url})
                  item['url'] = urlunparse(u'{schema};{netloc};/channels/play;;id={value};'.format(**params).split(';'))

            return self.m3uchanneltemplate.format(**item)
        params.update({'schema': 'http', 'netloc': params.get('hostport'), 'ext': query_get(params.get('query',''), 'ext', 'ts')})
        return ensure_binary(params.get('header', self.m3uemptyheader if params.get('empty_header') else self.m3uheader) + ''.join(map(line_generator, self.sort(self.itemlist))))
示例#3
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
示例#5
0
 def send_error(self, errorcode=500, logmsg='Dying with error', loglevel=logging.ERROR):
     '''
     Close connection with error
     '''
     try:
        self.send_response(errorcode)
        self.send_header('Content-Type', 'text/plain')
        self.send_header('Content-Length', len(logmsg))
        self.send_header('Connection', 'Close')
        self.end_headers()
        self.wfile.write(ensure_binary(logmsg))
     finally:
        logging.log(loglevel, logmsg)
        self.handlerGreenlet.kill()
示例#6
0
    def handleRequest(self):
        '''
        Main request handler path: /{reqtype}/{reqtype_value}/{file_indexes}/{developer_id}/{affiliate_id}/{zone_id}/{stream_id}/{fname}.{ext}
        '''
        logger = logging.getLogger('handleRequest')
        # Make handler parameters dict
        self.__dict__.update({}.fromkeys(
            aceclient.acemessages.AceConst.START_PARAMS, '0'
        ))  # [file_indexes, developer_id, affiliate_id, zone_id, stream_id]
        self.__dict__.update({
            k: v
            for (k, v) in
            [(aceclient.acemessages.AceConst.START_PARAMS[i - 3],
              self.splittedpath[i] if self.splittedpath[i].isdigit() else '0')
             for i in range(3, len(self.splittedpath))]
        })
        self.__dict__.update({
            self.reqtype:
            unquote(self.splittedpath[2]),  # {reqtype: reqtype_value}
            'ace':
            AceConfig.ace,
            'acesex':
            AceConfig.acesex,
            'aceage':
            AceConfig.aceage,
            'acekey':
            AceConfig.acekey,
            'connect_timeout':
            AceConfig.aceconntimeout,
            'result_timeout':
            AceConfig.aceresulttimeout,
            'videoseekback':
            AceConfig.videoseekback,
            'videotimeout':
            AceConfig.videotimeout,
            'stream_type':
            ' '.join([
                '{}={}'.format(k, v)
                for k, v in AceConfig.acestreamtype.items()
            ]),  # request http or hls from AceEngine
            'sessionID':
            self.handlerGreenlet.name[
                self.handlerGreenlet.name.rfind('-') +
                1:],  # Greenlet.minimal_ident A small, unique non-negative integer
            'connectionTime':
            gevent.time.time(),
            'clientDetail':
            None,
            'channelIcon':
            self.__dict__.get(
                'channelIcon',
                'http://static.acestream.net/sites/acestream/img/ACE-logo.png'
            ),
        })
        # End parameters dict
        try:
            self.q = gevent.queue.Queue(maxsize=AceConfig.videotimeout)
            transcoder = gevent.event.AsyncResult()
            out = self.wfile
            gevent.spawn(wrap_errors(gevent.socket.error,
                                     self.rfile.read)).link(
                                         lambda x: self.handlerGreenlet.kill()
                                     )  # Client disconection watchdog
            try:
                if not AceProxy.clientcounter.idleAce:
                    logger.debug(
                        'Create a connection with AceStream on {ace[aceHostIP]}:{ace[aceAPIport]}'
                        .format(**self.__dict__))
                    AceProxy.clientcounter.idleAce = aceclient.AceClient(
                        self.__dict__)
                    AceProxy.clientcounter.idleAce.GetAUTH()
                if self.reqtype not in ('direct_url', 'efile_url'):
                    self.__dict__.update(
                        AceProxy.clientcounter.idleAce.GetCONTENTINFO(
                            self.__dict__))
                    self.channelName = ensure_str(
                        self.__dict__.get(
                            'channelName',
                            next(
                                iter([
                                    x[0] for x in self.files
                                    if x[1] == int(self.file_indexes)
                                ]), 'NoNameChannel')))
                else:
                    self.channelName = ensure_str(
                        self.__dict__.get('channelName', 'NoNameChannel'))
                    self.infohash = requests.auth.hashlib.sha1(
                        ensure_binary(self.path)).hexdigest()
                AceProxy.clientcounter.idleAce._title = self.channelName
            except Exception as e:
                AceProxy.clientcounter.idleAce._read.kill()
                logging.debug('Error 404')
                self.send_error(404, '%s' % repr(e), logging.ERROR)

            self.ext = self.__dict__.get(
                'ext', self.channelName[self.channelName.rfind('.') + 1:])
            if self.ext == self.channelName:
                self.ext = query_get(self.query, 'ext', 'ts')
            mimetype = mimetypes.guess_type(
                '{channelName}.{ext}'.format(**self.__dict__))[0]
            try:
                # If &fmt transcode key present in request
                fmt = query_get(self.query, 'fmt')
                if fmt:
                    if AceConfig.osplatform != 'Windows':
                        if fmt in AceConfig.transcodecmd:
                            stderr = None if AceConfig.loglevel == logging.DEBUG else DEVNULL
                            popen_params = {
                                'bufsize': 1048576,
                                'stdin': gevent.subprocess.PIPE,
                                'stdout': self.wfile,
                                'stderr': stderr,
                                'shell': False
                            }
                            try:
                                gevent.spawn(lambda: psutil.Popen(
                                    AceConfig.transcodecmd[fmt], **popen_params
                                )).link(transcoder)
                                out = transcoder.get(timeout=2.0).stdin
                                logger.info(
                                    '[{channelName}]: Transcoding to [{clientip}] started'
                                    .format(**self.__dict__))
                            except:
                                logger.error(
                                    '[{channelName}]: Error starting transcoding to [{clientip}]! Is ffmpeg or VLC installed?'
                                    .format(**self.__dict__))
                        else:
                            logger.error(
                                "[{channelName}]: Can't found fmt key. Transcoding to [{clientip}] not started!"
                                .format(**self.__dict__))
                    elif AceConfig.osplatform == 'Windows':
                        logger.error(
                            '[{channelName}]: Not applicable in Windnows OS. Transcoding to [{clientip}] not started!'
                            .format(**self.__dict__))

                if AceProxy.clientcounter.addClient(self) == 1:
                    # Create broadcast if it does not exist yet
                    gevent.spawn(
                        StreamReader,
                        self.ace.GetBroadcastStartParams(self.__dict__)
                    ).link(lambda x: logger.debug(
                        '[{channelName}]: Broadcast destroyed. Last client disconnected'
                        .format(**self.__dict__)))
                    logger.debug('[{channelName}]: Broadcast created'.format(
                        **self.__dict__))
                else:
                    logger.debug(
                        '[{channelName}]: Broadcast already exists'.format(
                            **self.__dict__))
                logger.info(
                    '[{channelName}]: Streaming to [{clientip}] started'.
                    format(**self.__dict__))
                # Sending videostream headers to client
                response_use_chunked = False if (
                    transcoder.value or self.request_version
                    == 'HTTP/1.0') else AceConfig.use_chunked
                drop_headers = []
                proxy_headers = {
                    'Connection': 'keep-alive',
                    'Keep-Alive':
                    'timeout=%s, max=100' % AceConfig.videotimeout,
                    'Accept-Ranges': 'none',
                    'Transfer-Encoding': 'chunked',
                    'Content-Type':
                    'video/MP2T' if mimetype is None else mimetype,
                }

                if not response_use_chunked:
                    self.protocol_version = 'HTTP/1.0'
                    proxy_headers['Connection'] = 'Close'
                    drop_headers.extend(['Transfer-Encoding', 'Keep-Alive'])

                response_headers = [(k, v) for (k, v) in proxy_headers.items()
                                    if k not in drop_headers]
                self.send_response(200)
                logger.debug('[%s]: Sending HTTPAceProxy headers: %s' %
                             (self.clientip, dict(response_headers)))
                gevent.joinall([
                    gevent.spawn(self.send_header, k, v)
                    for (k, v) in response_headers
                ])
                self.end_headers()
                # write data to client while it is alive
                for chunk in self.q:
                    out.write(b'%X\r\n%s\r\n' %
                              (len(chunk),
                               chunk) if response_use_chunked else chunk)

            except aceclient.AceException as e:
                _ = AceProxy.pool.map(
                    lambda x: x.send_error(500, repr(e), logging.ERROR),
                    AceProxy.clientcounter.getClientsList(self.infohash))
            except gevent.socket.error:
                pass  # Client disconnected

        except gevent.GreenletExit:
            AceProxy.clientcounter.idleAce._read.kill()

        finally:
            AceProxy.clientcounter.deleteClient(self)
            logger.info(
                '[{channelName}]: Streaming to [{clientip}] finished'.format(
                    **self.__dict__))
            if transcoder.value:
                try:
                    transcoder.value.kill()
                    logger.info(
                        '[{channelName}]: Transcoding to [{clientip}] stoped'.
                        format(**self.__dict__))
                except:
                    pass
    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))
示例#8
0
 def READY(request_key='', product_key=AceConst.ACE_KEY):
     return 'READY key={}-{}'.format(
         product_key.split('-')[0],
         hashlib.sha1(ensure_binary(request_key + product_key)).hexdigest())
示例#9
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