Exemplo n.º 1
0
    def handle(self, connection, headers_only=False):
        self.params = parse_qs(connection.query)
        path_file_ext = ''.join(connection.path.split('.')[-1:])

        if headers_only:
            self.SendResponse(200, 'json', '', connection)
            return

        if connection.path == '/stat':
            if self.params.get('action', [''])[0] == 'get_status':
                self.SendResponse(
                    200, 'json',
                    json.dumps(self.getStatusJSON(),
                               ensure_ascii=False).encode('utf-8'), connection)
            else:
                try:
                    self.SendResponse(200, 'html',
                                      self.getReqFileContent('index.html'),
                                      connection)
                except:
                    connection.dieWithError(404, 'Not Found')
                    return

        elif path_file_ext:
            try:
                self.SendResponse(
                    200, path_file_ext,
                    self.getReqFileContent(
                        connection.path.replace(r'/stat', '')), connection)
            except:
                connection.dieWithError(404, 'Not Found')
                return
        else:
            connection.dieWithError(404, 'Not Found')
Exemplo n.º 2
0
    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 torrent-telik.m3u playlist')
           connection.wfile.write(exported)
Exemplo n.º 3
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)
Exemplo n.º 4
0
    def handle(self, connection, headers_only=False):

        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)
        exported = self.createPlaylist(connection.headers['Host'],
                                       connection.reqtype,
                                       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)
Exemplo n.º 5
0
    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))
Exemplo n.º 6
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

        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.json()['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', '*')
        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)
Exemplo n.º 7
0
    def handleRequest(self,
                      headers_only,
                      channelName=None,
                      channelIcon=None,
                      fmt=None):
        logger = logging.getLogger('HandleRequest')
        self.reqparams, self.path = parse_qs(
            self.query), self.path[:-1] if self.path.endswith(
                '/') else self.path

        self.videoextdefaults = ('.3gp', '.aac', '.ape', '.asf', '.avi', '.dv',
                                 '.divx', '.flac', '.flc', '.flv', '.m2ts',
                                 '.m4a', '.mka', '.mkv', '.mpeg', '.mpeg4',
                                 '.mpegts', '.mpg4', '.mp3', '.mp4', '.mpg',
                                 '.mov', '.m4v', '.ogg', '.ogm', '.ogv',
                                 '.oga', '.ogx', '.qt', '.rm', '.swf', '.ts',
                                 '.vob', '.wmv', '.wav', '.webm')

        # Limit on the number of connected clients
        if 0 < AceConfig.maxconns <= AceProxy.clientcounter.totalClients():
            self.dieWithError(
                501,
                "Maximum client connections reached, can't serve request from %s"
                % self.clientip, logging.ERROR)
            return
        # Check if third parameter exists…/self.reqtype/blablablablabla/video.mpg
        # And if it ends with regular video extension
        try:
            if not self.path.endswith(self.videoextdefaults):
                self.dieWithError(
                    501,
                    'Request seems like valid but no valid video extension was provided',
                    logging.ERROR)
                return
        except IndexError:
            self.dieWithError(400, 'Bad Request',
                              logging.WARNING)  # 400 Bad Request
            return
        # Pretend to work fine with Fake or HEAD request.
        if headers_only or AceConfig.isFakeRequest(self.path, self.query,
                                                   self.headers):
            # Return 200 and exit
            if headers_only:
                logger.debug('Sending headers and closing connection')
            else:
                logger.debug('Fake request - closing connection')
            self.send_response(200)
            self.send_header('Content-Type', 'video/mp2t')
            self.send_header('Connection', 'Close')
            self.end_headers()
            return
        # Check is AceEngine alive
        checkAce()
        # Make dict with parameters
        # [file_indexes, developer_id, affiliate_id, zone_id, stream_id]
        paramsdict = {}.fromkeys(aceclient.acemessages.AceConst.START_PARAMS,
                                 '0')
        for i in range(3, len(self.splittedpath)):
            paramsdict[aceclient.acemessages.AceConst.START_PARAMS[
                i - 3]] = self.splittedpath[i] if self.splittedpath[i].isdigit(
                ) else '0'
        paramsdict[self.reqtype] = unquote(
            self.splittedpath[2])  #self.path_unquoted
        #End parameters dict
        CID = NAME = None
        if not AceConfig.new_api:
            try:
                if not AceProxy.clientcounter.idleAce:
                    logger.debug('Create connection to AceEngine.....')
                    AceProxy.clientcounter.idleAce = aceclient.AceClient(
                        AceProxy.clientcounter, AceConfig.ace,
                        AceConfig.aceconntimeout, AceConfig.aceresulttimeout)
                    AceProxy.clientcounter.idleAce.aceInit(
                        AceConfig.acesex, AceConfig.aceage, AceConfig.acekey,
                        AceConfig.videoseekback, AceConfig.videotimeout)
                CID, NAME = AceProxy.clientcounter.idleAce.GETINFOHASH(
                    self.reqtype, paramsdict[self.reqtype],
                    paramsdict['file_indexes'])
            except aceclient.AceException as e:
                self.dieWithError(503, '%s' % repr(e), logging.ERROR)
                AceProxy.clientcounter.idleAce = None
                return
        else:
            try:
                with requests.session() as s:
                    s.stream = s.verify = False
                    url = 'http://%s:%s/ace/%s' % (
                        AceConfig.ace['aceHostIP'],
                        AceConfig.ace['aceHTTPport'], 'manifest.m3u8'
                        if AceConfig.acestreamtype['output_format'] == 'hls'
                        else 'getstream')
                    params = {
                        'id' if self.reqtype in ('cid', 'content_id') else self.reqtype:
                        paramsdict[self.reqtype],
                        'format':
                        'json',
                        'pid':
                        str(uuid4()),
                        '_idx':
                        paramsdict['file_indexes']
                    }
                    if AceConfig.acestreamtype['output_format'] == 'hls':
                        params.update(AceConfig.acestreamtype)
                        del params['output_format']
                    self.cmd = s.get(
                        url,
                        params=params,
                        timeout=(5, AceConfig.videotimeout)).json()['response']
                    CID = urlparse(self.cmd['playback_url']).path.split('/')[3]
                    url = 'http://%s:%s/server/api' % (
                        AceConfig.ace['aceHostIP'],
                        AceConfig.ace['aceHTTPport'])
                    params = {
                        'method': 'get_media_files',
                        self.reqtype: paramsdict[self.reqtype]
                    }
                    NAME = s.get(url,
                                 params=params,
                                 timeout=(5, AceConfig.aceresulttimeout)).json(
                                 )['result'][paramsdict['file_indexes']]
            except Exception as e:
                self.dieWithError(503, '%s' % repr(e), logging.ERROR)
                return

        self.connectionTime = gevent.time.time()
        self.channelName = NAME if not channelName else channelName
        self.channelIcon = 'http://static.acestream.net/sites/acestream/img/ACE-logo.png' if not channelIcon else channelIcon
        self.clientInfo = self.transcoder = None
        try:
            self.connectGreenlet = gevent.spawn(
                self.connectDetector)  # client disconnection watchdog
            self.out = self.wfile
            # If &fmt transcode key present in request
            fmt = self.reqparams.get('fmt', [''])[0]
            if fmt and 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:
                        self.transcoder = gevent.event.AsyncResult()
                        gevent.spawn(lambda: psutil.Popen(
                            AceConfig.transcodecmd[fmt], **popen_params)).link(
                                self.transcoder)
                        self.transcoder = self.transcoder.get(timeout=2.0)
                        self.out = self.transcoder.stdin
                        logger.info('Transcoding for %s started' %
                                    self.clientip)
                    except:
                        logger.error(
                            'Error starting transcoding! Is Ffmpeg or VLC installed?'
                        )
                        self.transcoder = None
                        self.out = self.wfile
                else:
                    logger.error(
                        "Can't found fmt key. Transcoding not started!")

            self.response_use_chunked = False if self.transcoder is not None else AceConfig.use_chunked

            if AceProxy.clientcounter.addClient(CID, self) == 1:
                # If there is no existing broadcast we create it
                playback_url = self.cmd[
                    'playback_url'] if AceConfig.new_api else self.ace.START(
                        self.reqtype, paramsdict, AceConfig.acestreamtype)
                if not AceProxy.ace:  #Rewrite host:port for remote AceEngine
                    playback_url = urlparse(playback_url)._replace(
                        netloc='%s:%s' %
                        (AceConfig.ace['aceHostIP'],
                         AceConfig.ace['aceHTTPport'])).geturl()
                gevent.spawn(StreamReader, playback_url, CID)

            # Sending videostream headers to client
            logger.info('Streaming "%s" to %s started' %
                        (self.channelName, self.clientip))
            drop_headers = []
            proxy_headers = {
                'Connection': 'keep-alive',
                'Keep-Alive': 'timeout=15, max=100',
                'Accept-Ranges': 'none',
                'Transfer-Encoding': 'chunked',
                'Content-Type': 'application/octet-stream',
                'Cache-Control': 'max-age=0, no-cache, no-store',
                'Pragma': 'no-cache'
            }

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

            response_headers = [(k, v) for (k, v) in proxy_headers.items()
                                if k not in drop_headers]
            self.send_response(200)
            logger.debug('Sending HTTPAceProxy headers to client: %s' %
                         dict(response_headers))
            gevent.joinall([
                gevent.spawn(self.send_header, k, v)
                for (k, v) in response_headers
            ])
            self.end_headers()

            self.connectGreenlet.join(
            )  # Wait until request complite or client disconnected

        except aceclient.AceException as e:
            gevent.joinall([
                gevent.spawn(client.dieWithError, 503, '%s' % repr(e),
                             logging.ERROR)
                for client in AceProxy.clientcounter.getClientsList(CID)
            ])
            gevent.joinall([
                gevent.spawn(client.connectGreenlet.kill)
                for client in AceProxy.clientcounter.getClientsList(CID)
            ])
        except gevent.GreenletExit:
            pass  # Client disconnected
        except Exception as e:
            self.dieWithError(500, 'Unexpected error: %s' % repr(e))
        finally:
            logging.info('Streaming "%s" to %s finished' %
                         (self.channelName, self.clientip))
            if self.transcoder:
                try:
                    self.transcoder.kill()
                    logging.info('Transcoding for %s stoped' % self.clientip)
                except:
                    pass
            if AceProxy.clientcounter.deleteClient(CID, self) == 0:
                if AceConfig.new_api:
                    with requests.get(self.cmd['command_url'],
                                      params={'method': 'stop'},
                                      timeout=5) as r:
                        logging.debug('Stop broadcast: %s' % r.json())
                logging.debug(
                    'Broadcast "%s" stoped. Last client %s disconnected' %
                    (self.channelName, self.clientip))
Exemplo n.º 8
0
def query_get(query, key, default=''):
    '''
    Helper for getting values from a pre-parsed query string
    '''
    return parse_qs(query).get(key, [default])[0]
Exemplo n.º 9
0
    def exportm3u(self, hostport, _bytearray=bytearray, **params):
        '''
        Exports m3u playlist
        :params: dict with keys: 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').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
                    item['url'] = urlunparse(
                        u'{schema};{netloc};/archive/play?id={url};;{query};'.
                        format(**params).split(';'))
                elif not params.get('archive') and url.isdigit(
                ):  # For channel id's
                    item['url'] = urlunparse(
                        u'{schema};{netloc};/channels/play?id={url};;{query};'.
                        format(**params).split(';'))

            return self.m3uchanneltemplate.format(**item)

        params.update({
            'schema': 'http',
            'netloc': hostport
        })  # Adding ts:// after http:// for some players
        params.update(
            {'ext': parse_qs(params.get('query', '')).get('ext', ['ts'])[0]})
        header = params.get('header')
        if header is None:
            header = self.m3uemptyheader if params.get(
                'empty_header') else self.m3uheader
        return _bytearray(
            header +
            ''.join(Group().map(line_generator, self.sort(self.itemlist))),
            'utf-8')
Exemplo n.º 10
0
    def handleRequest(self,
                      headers_only,
                      channelName=None,
                      channelIcon=None,
                      fmt=None):

        logger = logging.getLogger('HandleRequest')
        self.reqparams, self.path = parse_qs(
            self.query), self.path[:-1] if self.path.endswith(
                '/') else self.path

        videoextdefaults = ('.avi', '.flv', '.m2ts', '.mkv', '.mpeg', '.mpeg4',
                            '.mpegts', '.mpg4', '.mp4', '.mpg', '.mov', '.mpv',
                            '.qt', '.ts', '.wmv')

        # Limit on the number of connected clients
        if 0 < AceConfig.maxconns <= len(
                AceProxy.clientcounter.getAllClientsList()):
            self.dieWithError(
                403,
                "Maximum client connections reached, can't serve request from %s"
                % self.clientip, logging.ERROR)
            return
        # Check if third parameter exists…/pid/blablablablabla/video.mpg
        #                                                     |_________|
        # And if it ends with regular video extension
        try:
            if not self.path.endswith(videoextdefaults):
                self.dieWithError(
                    501,
                    'Request seems like valid but no valid video extension was provided',
                    logging.ERROR)
                return
        except IndexError:
            self.dieWithError(400, 'Bad Request',
                              logging.WARNING)  # 400 Bad Request
            return
        # Pretend to work fine with Fake or HEAD request.
        if headers_only or AceConfig.isFakeRequest(self.path, self.query,
                                                   self.headers):
            # Return 200 and exit
            if headers_only:
                logger.debug('Sending headers and closing connection')
            else:
                logger.debug('Fake request - closing connection')
            self.send_response(200)
            self.send_header('Content-Type', 'video/mp2t')
            self.send_header('Connection', 'Close')
            self.end_headers()
            self.closeConnection()
            return

        # Make dict with parameters
        # [file_indexes, developer_id, affiliate_id, zone_id, stream_id]
        paramsdict = {}.fromkeys(aceclient.acemessages.AceConst.START_PARAMS,
                                 '0')
        for i in range(3, len(self.splittedpath)):
            paramsdict[aceclient.acemessages.AceConst.START_PARAMS[
                i - 3]] = self.splittedpath[i] if self.splittedpath[i].isdigit(
                ) else '0'
        paramsdict[self.reqtype] = unquote(
            self.splittedpath[2])  #self.path_unquoted
        #End parameters dict

        self.connectionTime = gevent.time.time()
        self.sessionID = str(uuid4().int)[:8]
        self.clientInfo = self.transcoder = None
        self.channelIcon = 'http://static.acestream.net/sites/acestream/img/ACE-logo.png' if channelIcon is None else channelIcon

        try:
            if not AceProxy.clientcounter.idleAce:
                logger.debug('Create connection to AceEngine.....')
                AceProxy.clientcounter.idleAce = aceclient.AceClient(
                    AceProxy.clientcounter, AceConfig.ace,
                    AceConfig.aceconntimeout, AceConfig.aceresulttimeout)
                AceProxy.clientcounter.idleAce.aceInit(AceConfig.acesex,
                                                       AceConfig.aceage,
                                                       AceConfig.acekey,
                                                       AceConfig.videoseekback,
                                                       AceConfig.videotimeout)
            self.CID, self.channelName = AceProxy.clientcounter.idleAce.GETINFOHASH(
                self.reqtype, paramsdict[self.reqtype], self.sessionID,
                paramsdict['file_indexes'])
        except aceclient.AceException as e:
            AceProxy.clientcounter.idleAce = None
            self.dieWithError(404, '%s' % repr(e), logging.ERROR)
            return
        mimetype = mimetypes.guess_type(self.channelName)[0]
        try:
            gevent.spawn(wrap_errors(
                gevent.socket.error, self.rfile.read)).link(
                    lambda x: self.finish())  # Client disconection watchdog
            self.q = gevent.queue.Queue(maxsize=AceConfig.videotimeout)
            self.out = self.wfile
            # If &fmt transcode key present in request
            if fmt is None: fmt = self.reqparams.get('fmt', [''])[0]
            if fmt and 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:
                        self.transcoder = gevent.event.AsyncResult()
                        AceProxy.spawn(lambda: psutil.Popen(
                            AceConfig.transcodecmd[fmt], **popen_params)).link(
                                self.transcoder)
                        self.transcoder = self.transcoder.get(timeout=2.0)
                        self.out = self.transcoder.stdin
                        logger.info('Transcoding for %s started' %
                                    self.clientip)
                    except:
                        logger.error(
                            'Error starting transcoding! Is Ffmpeg or VLC installed?'
                        )
                        self.transcoder = None
                        self.out = self.wfile
                else:
                    logger.error(
                        "Can't found fmt key. Transcoding not started!")

            # Start broadcast if it does not exist
            if AceProxy.clientcounter.addClient(self) == 1:
                playback_url = self.ace.START(self.reqtype, paramsdict,
                                              AceConfig.acestreamtype)
                AceProxy.pool.spawn(
                    StreamReader, playback_url,
                    self.CID).link(lambda x: logging.debug(
                        'Broadcast "%s" stoped. Last client disconnected' %
                        self.channelName))

            logger.info('Streaming "%s" to %s started' %
                        (self.channelName, self.clientip))
            # Sending videostream headers to client
            self.response_use_chunked = False if (
                self.transcoder is not None or self.request_version
                == 'HTTP/1.0') else AceConfig.use_chunked
            drop_headers = []
            proxy_headers = {
                'Connection': 'keep-alive',
                'Keep-Alive': 'timeout=15, max=100',
                'Accept-Ranges': 'none',
                'Transfer-Encoding': 'chunked',
                'Content-Type': 'video/MP2T' if mimetype is None else mimetype,
                'Pragma': 'no-cache',
                'Cache-Control': 'max-age=0, no-cache, no-store'
            }

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

            response_headers = [(k, v) for (k, v) in proxy_headers.items()
                                if k not in drop_headers]
            self.send_response(200)
            logger.debug('Sending HTTPAceProxy headers to client: %s' %
                         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 he is alive
            for chunk in self.q:
                self.out.write(chunk)

        except aceclient.AceException as e:
            AceProxy.pool.map(
                lambda x: x.dieWithError(500, repr(e), logging.ERROR),
                AceProxy.clientcounter.getClientsList(self.CID))
        except (gevent.GreenletExit, gevent.socket.error):
            pass  # Client disconnected
        finally:
            AceProxy.clientcounter.deleteClient(self)
            logging.info('Streaming "%s" to %s finished' %
                         (self.channelName, self.clientip))
            if self.transcoder:
                try:
                    self.transcoder.kill()
                    logging.info('Transcoding for %s stoped' % self.clientip)
                except:
                    pass
            self.closeConnection()
Exemplo n.º 11
0
    def handleRequest(self, **params):
        '''
        :params: dict() with keys: headers_only, channelName, channelIcon
        '''

        logger = logging.getLogger('HandleRequest')
        self.path = self.path[:-1] if self.path.endswith('/') else self.path

        # Limit on the number of connected clients
        if 0 < AceConfig.maxconns <= len(
                AceProxy.clientcounter.getAllClientsList()):
            self.dieWithError(
                403,
                "Maximum client connections reached, can't serve request from %s"
                % self.clientip, logging.ERROR)
            return
        # Check if third parameter exists…/pid/blablablablabla/video.mpg
        #                                                     |_________|
        # And if it ends with regular video extension
        try:
            if not self.path.endswith(
                ('.avi', '.flv', '.m2ts', '.mkv', '.mpeg', '.mpeg4', '.mpegts',
                 '.mpg4', '.mp4', '.mpg', '.mov', '.mpv', '.qt', '.ts',
                 '.wmv')):
                self.dieWithError(
                    501,
                    'Request seems like valid but no valid video extension was provided',
                    logging.ERROR)
                return
        except IndexError:
            self.dieWithError(400, 'Bad Request',
                              logging.WARNING)  # 400 Bad Request
            return
        # Pretend to work fine with Fake or HEAD request.
        if params.get('headers_only') or AceConfig.isFakeRequest(
                self.path, self.query, self.headers):
            # Return 200 and exit
            if params.get('headers_only'):
                logger.debug('Sending headers and closing connection')
            else:
                logger.debug('Fake request - closing connection')
            self.send_response(200)
            self.send_header('Content-Type', 'video/mp2t')
            self.send_header('Connection', 'Close')
            self.end_headers()
            self.closeConnection()
            return

        # Make parameters dict
        params.update({self.reqtype:
                       unquote(self.splittedpath[2])})  # {command: value}
        params.update(
            {}.fromkeys(aceclient.acemessages.AceConst.START_PARAMS, '0')
        )  # [file_indexes, developer_id, affiliate_id, zone_id, stream_id]
        params.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))]
        })
        params.update({
            'stream_type':
            ' '.join([
                '{}={}'.format(k, v)
                for k, v in AceConfig.acestreamtype.items()
            ])
        })  # request http or hls from AceEngine
        params['request_id'] = self.sessionID = str(uuid4().int)[:8]
        # End parameters dict

        self.connectionTime = gevent.time.time()
        self.clientInfo = None
        self.channelIcon = params.get('channelIcon')
        if self.channelIcon is None:
            self.channelIcon = 'http://static.acestream.net/sites/acestream/img/ACE-logo.png'

        try:
            if not AceProxy.clientcounter.idleAce:
                logger.debug(
                    'Create connection with AceStream on {aceHostIP}:{aceAPIport}'
                    .format(**AceConfig.ace))
                AceProxy.clientcounter.idleAce = aceclient.AceClient(
                    AceConfig.ace, AceConfig.aceconntimeout,
                    AceConfig.aceresulttimeout)
                AceProxy.clientcounter.idleAce.GetAUTH(AceConfig.acesex,
                                                       AceConfig.aceage,
                                                       AceConfig.acekey,
                                                       AceConfig.videoseekback,
                                                       AceConfig.videotimeout)
            if self.reqtype not in ('direct_url', 'efile_url'):
                self.CID, self.channelName = AceProxy.clientcounter.idleAce.GetCONTENTINFO(
                    params)
            else:
                self.channelName = params.get('channelName')
                if self.channelName is None: self.channelName = 'NoNameChannel'
                self.CID = requests.auth.hashlib.sha1(
                    self.channelName.encode('utf-8')).hexdigest()
        except aceclient.AceException as e:
            AceProxy.clientcounter.idleAce = None
            self.dieWithError(404, '%s' % repr(e), logging.ERROR)
            return
        ext = self.channelName[self.channelName.rfind('.') + 1:]
        if ext == self.channelName:
            ext = parse_qs(self.query).get('ext', ['ts'])[0]
        mimetype = mimetypes.guess_type('%s.%s' % (self.channelName, ext))[0]
        try:
            AceProxy.pool.spawn(
                wrap_errors(gevent.socket.error, self.rfile.read)).link(
                    lambda x: self.finish())  # Client disconection watchdog
            self.q = gevent.queue.Queue(maxsize=AceConfig.videotimeout)
            out = self.wfile
            # If &fmt transcode key present in request
            fmt = parse_qs(self.query).get('fmt', [''])[0]
            transcoder = gevent.event.AsyncResult()
            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:
                            #transcoder = gevent.event.AsyncResult()
                            AceProxy.pool.spawn(lambda: psutil.Popen(
                                AceConfig.transcodecmd[fmt], **popen_params)
                                                ).link(transcoder)
                            out = transcoder.get(timeout=2.0).stdin
                            logger.info(
                                'Transcoding for {clientip} started'.format(
                                    **self.__dict__))
                        except:
                            logger.error(
                                'Error starting transcoding! Is Ffmpeg or VLC installed?'
                            )
                    else:
                        logger.error(
                            "Can't found fmt key. Transcoding not started!")
                elif AceConfig.osplatform == 'Windows':
                    logger.error(
                        'Not applicable in Windnows OS. Transcoding not started!'
                    )

            # Start broadcast if it does not exist
            if AceProxy.clientcounter.addClient(self) == 1:
                START = self.ace.GetBroadcastStartParams(params)
                self.broadcast = AceProxy.pool.spawn(StreamReader,
                                                     START['url'],
                                                     START['infohash'])
                self.broadcast.link(lambda x: logging.debug(
                    'Broadcast "{channelName}" stoped. Last client disconnected'
                    .format(**self.__dict__)))

            logger.info(
                'Streaming "{channelName}" to {clientip} started'.format(
                    **self.__dict__))
            # Sending videostream headers to client
            response_use_chunked = False if (
                transcoder is not None 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('Sending HTTPAceProxy headers to client: %s' %
                         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 he is alive
            for chunk in self.q:
                out.write(b'%x\r\n' % len(chunk) + chunk +
                          b'\r\n' if response_use_chunked else chunk)

        except aceclient.AceException as e:
            _ = AceProxy.pool.map(
                lambda x: x.dieWithError(500, repr(e), logging.ERROR),
                AceProxy.clientcounter.getClientsList(self.CID))
        except (gevent.GreenletExit, gevent.socket.error):
            pass  # Client disconnected
        finally:
            AceProxy.clientcounter.deleteClient(self)
            logging.info(
                'Streaming "{channelName}" to {clientip} finished'.format(
                    **self.__dict__))
            if transcoder.value:
                try:
                    transcoder.value.kill()
                    logging.info('Transcoding for {clientip} stoped'.format(
                        **self.__dict__))
                except:
                    pass
            self.closeConnection()
            return
Exemplo n.º 12
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 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 = config.logobase + 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.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
                    }
                    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')
                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:
                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': 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')

            if headers_only:
                connection.end_headers()
                return

            translations_list = TorrentTvApi(config.email,
                                             config.password).translations(
                                                 'all', True)
            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,
                                                 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')
                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')

                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] 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,
                                                 empty_header=True,
                                                 process_url=False,
                                                 fmt=self.params.get(
                                                     'fmt',
                                                     [''])[0]).encode('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('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')
                    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.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 = 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:
                    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 = 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,
                                                 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')
                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.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')
                    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 == '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 = '" + config.logobase + "'\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')
Exemplo n.º 13
0
    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 = 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/'):
            name = path.rsplit('.', 1)
            if not name[1]:
                connection.dieWithError(404,
                                        'Invalid path: %s' % unquote(path),
                                        logging.ERROR)
                return
            name = unquote(name[0].rsplit('/', 1)[1])
            if isinstance(name, bytes): name = name.decode('utf-8')  # PY2
            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' % 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:
            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',
                '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.logomap.get(name),
                                     fmt=params.get('fmt', [''])[0])
        elif not headers_only:
            self.logger.debug('Exporting m3u playlist')
            connection.wfile.write(exported)