Beispiel #1
0
    def _oauth_token(self, data):
        token_data = self._session.post(
            'https://auth.kayosports.com.au/oauth/token', json=data).json()
        if 'error' in token_data:
            raise APIError(
                _(_.LOGIN_ERROR, msg=token_data.get('error_description')))

        account_status = None
        try:
            b64_string = token_data['access_token'].split('.')[1]
            b64_string += "=" * ((4 - len(b64_string) % 4) % 4)  #fix padding

            data = json.loads(b64decode(b64_string))
            account_status = data['https://kayosports.com.au/status'][
                'account_status']
        except:
            log.debug('Failed to get account status')

        if account_status and account_status != 'ACTIVE_SUBSCRIPTION':
            raise APIError(_.INVALID_SUBSCRIPTION)

        userdata.set('access_token', token_data['access_token'])
        userdata.set('expires', int(time() + token_data['expires_in'] - 15))

        if 'refresh_token' in token_data:
            userdata.set('refresh_token', token_data['refresh_token'])

        self._set_authentication()
Beispiel #2
0
def gzip_extract(in_path):
    log.debug('Gzip Extracting: {}'.format(in_path))

    out_path = in_path + '.extract'

    try:
        with codecs.open(out_path, 'wb') as f_out, gzip.open(in_path,
                                                             'rb') as f_in:
            shutil.copyfileobj(f_in, f_out, length=CHUNKSIZE)
    except IOError:
        log.debug(
            'Failed to extract using python gzip (Known Kodi Android bug)')
        remove_file(out_path)
    else:
        shutil.move(out_path, in_path)
        return

    gzbin = find_gz()
    if not gzbin:
        remove_file(in_path)
        raise Error(_.NO_GZIP_BINARY)

    gz_path = in_path + '.gz'
    remove_file(gz_path)

    shutil.move(in_path, gz_path)
    call([gzbin, '-d', gz_path])

    if os.path.exists(gz_path):
        remove_file(gz_path)
        raise Error(_(_.GZIP_FAILED, path=gz_path))
Beispiel #3
0
def play(id, start_from=0, play_type=FROM_LIVE, **kwargs):
    asset = api.stream(id)
    start_from = int(start_from)
    play_type = int(play_type)
    is_live = kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX

    now = arrow.now()
    start = arrow.get(asset.get('preCheckTime', asset['transmissionTime']))
    if start > now:
        raise PluginError(
            _(_.GAME_NOT_STARTED,
              start=_makeHumanised(now, start).upper() + ' ' +
              _makeTime(start)))

    streams = [asset['recommendedStream']]
    streams.extend(asset['alternativeStreams'])
    streams = [s for s in streams if s['mediaFormat'] in SUPPORTED_FORMATS]

    if not streams:
        raise PluginError(_.NO_STREAM)

    provider = PREFER_PROVIDER or api.cdn_selection(
        'live' if is_live else 'vod')
    streams = sorted(
        streams,
        key=lambda k:
        (k['provider'] == provider, k['mediaFormat'] == PREFER_FORMAT),
        reverse=True)
    stream = streams[0]

    log.debug('Stream CDN: {provider} | Stream Format: {mediaFormat}'.format(
        **stream))

    item = plugin.Item(
        path=stream['manifest']['uri'],
        art=False,
        headers=HEADERS,
    )

    if is_live and (
            play_type == FROM_LIVE or (play_type == FROM_CHOOSE and gui.yes_no(
                _.PLAY_FROM, yeslabel=_.FROM_LIVE, nolabel=_.FROM_START))):
        start_from = 0

    if stream['mediaFormat'] == FORMAT_DASH:
        item.inputstream = inputstream.MPD()
    elif stream['mediaFormat'] == FORMAT_HLS_TS:
        hls = inputstream.HLS()

        if is_live and start_from == 0 and not hls.check():
            raise PluginError(_.HLS_REQUIRED)
        else:
            item.inputstream = hls

    if start_from:
        item.properties['ResumeTime'] = start_from
        item.properties['TotalTime'] = start_from

    return item
Beispiel #4
0
def find_gz():
    log.debug('Searching for Gzip binary...')

    for gzbin in [
            '/bin/gzip', '/usr/bin/gzip', '/usr/local/bin/gzip',
            '/system/bin/gzip'
    ]:
        if os.path.exists(gzbin):
            log.debug('Gzip binary found: {}'.format(gzbin))
            return gzbin

    return None
    def _load(self):
        try:
            with codecs.open(os.path.join(ADDON_PROFILE, CHANNELS_FILE),
                             'r',
                             encoding='utf8') as f:
                self._channels = json.load(f)
        except:
            log.debug('Failed to load channels file')
            self._channels = []

        try:
            with codecs.open(os.path.join(ADDON_PROFILE, OVERRIDE_FILE),
                             'r',
                             encoding='utf8') as f:
                self._overrides = json.load(f)
        except:
            log.debug('Failed to load overrides file')
            self._overrides = {}

        for key in self._overrides:
            if self._overrides[key].get('_added'):
                self._channels.append({
                    '_url': key,
                    '_name': '',
                    '_source': ''
                })

        last_chn_no = 0
        for channel in self._channels:
            channel['_id'] = channel.get('tvg-id') or channel['_url']
            channel['_hidden'] = settings.getBool('default_hidden', False)
            channel['_modified'] = False

            try:
                channel['tvg-chno'] = int(channel['tvg-chno'])
                last_chn_no = channel['tvg-chno']
            except:
                last_chn_no += 1
                channel['tvg-chno'] = last_chn_no

            overrides = None

            if 'tvg-id' in channel:
                overrides = self._overrides.get(channel['tvg-id'])

            if not overrides:
                overrides = self._overrides.get(channel['_url'])

            if overrides:
                channel['_modified'] = True
                channel.update(overrides)
Beispiel #6
0
def merge_epgs(epgs, output_dir):
    log.debug('Merging {} EPGs...'.format(len(epgs)))

    merged_path = os.path.join(output_dir, '.iptv_merge_epg')

    with codecs.open(merged_path, 'w', encoding='utf8') as outfile:
        outfile.write(
            u'<?xml version="1.0" encoding="utf-8" ?><tv generator-info-name="{}">'
            .format(ADDON_ID))

        parser = Parser(outfile)

        for epg in epgs:
            try:
                file_path = os.path.join(output_dir, '.iptv_merge_tmp')
                remove_file(file_path)
                process_file(epg, METHOD_EPG, file_path)

                log.debug('Processing: {}'.format(epg.path))
                parser.parse(file_path)

                remove_file(file_path)
            except Exception as e:
                log.debug('Skipping failed EPG: {}'.format(epg.path))
                log.exception(e)

        outfile.write(u'</tv>')

    log.debug('Merging EPGs Done')

    save_epg_channels(parser.channels)

    return merged_path
Beispiel #7
0
    def get_subtitles(self, captions):
        subtitles = []

        for idx, caption in enumerate(captions):
            try:
                r = self._session.get(caption['file'])
                reader = detect_format(r.text)
                srt = SRTWriter().write(reader().read(r.text))
            except:
                log.debug('Failed to parse subtitle: {}'.format(
                    caption['file']))
            else:
                srtfile = xbmc.translatePath(
                    'special://temp/curiosity{}.{}.srt'.format(
                        idx, caption['code'])).decode('utf-8')

                with codecs.open(srtfile, "w", "utf-8") as f:
                    f.write(srt)

                subtitles.append(srtfile)

        return subtitles
Beispiel #8
0
def process_file(item, method_name, file_path):
    if item.path_type == Source.TYPE_ADDON:
        addon = xbmcaddon.Addon(item.path)
        addon_id = addon.getAddonInfo('id')
        addon_path = xbmc.translatePath(addon.getAddonInfo('path'))
        merge_path = os.path.join(addon_path, MERGE_SETTING_FILE)

        with open(merge_path) as f:
            data = json.load(f)

        item.path = data[method_name].replace('$ID', addon_id).replace(
            '$FILE', file_path)

        if item.path.lower().startswith('plugin'):
            call_addon_method(item.path)
            return

        if item.path.lower().startswith('http'):
            item.path_type = Source.TYPE_REMOTE
        else:
            item.path_type = Source.TYPE_LOCAL

        if item.path.lower().endswith('.gz'):
            item.file_type = Source.FILE_GZIP

    if item.path_type == Source.TYPE_REMOTE:
        log.debug('Downloading: {} > {}'.format(item.path, file_path))
        Session().chunked_dl(item.path, file_path)

    elif item.path_type == Source.TYPE_LOCAL:
        path = xbmc.translatePath(item.path)
        if not os.path.exists(path):
            raise Error(_(_.LOCAL_PATH_MISSING, path=path))

        log.debug('Copying local file: {} > {}'.format(path, file_path))
        shutil.copyfile(path, file_path)

    if item.file_type == Source.FILE_GZIP:
        gzip_extract(file_path)
Beispiel #9
0
def call(cmd):
    log.debug('Subprocess call: {}'.format(cmd))
    return subprocess.call(cmd)
Beispiel #10
0
def merge_playlists(playlists, output_dir):
    log.debug('Merging {} Playlists...'.format(len(playlists)))

    merged_path = os.path.join(output_dir, '.iptv_merge_playlist')

    channels = []
    last_chn_no = 0

    for playlist in playlists:
        try:
            file_path = os.path.join(output_dir, '.iptv_merge_tmp')
            remove_file(file_path)
            process_file(playlist, METHOD_PLAYLIST, file_path)

            log.debug('Processing: {}'.format(playlist.path))
            with codecs.open(file_path, 'r', encoding='utf8') as infile:
                found = None

                for line in infile:
                    line = line.strip()

                    if line.startswith('#EXTINF'):
                        found = line
                    elif found and line and not line.startswith('#'):
                        data = {
                            '_url': line,
                            '_name': '',
                            '_source': playlist.id
                        }

                        parse = urlparse(data['_url'])
                        if not parse.scheme or not parse.netloc:
                            found = None
                            continue

                        colon = found.find(':', 0)
                        comma = found.rfind(',', 0)

                        if colon >= 0 and comma >= 0 and comma > colon:
                            data['_name'] = found[comma + 1:].strip()

                        for key, value in re.findall('([\w-]+)="([^"]*)"',
                                                     found):
                            data[key] = value.strip()

                        channels.append(data)
                        found = None
        except Exception as e:
            log.debug('Skipping failed Playlist: {}'.format(playlist.path))
            log.exception(e)

        remove_file(file_path)

    Channels.set_channels(channels)

    with codecs.open(merged_path, 'w', encoding='utf8') as outfile:
        outfile.write(u'#EXTM3U')

        for channel in Channels().playlist():
            id = channel.pop('_id')
            hidden = channel.pop('_hidden',
                                 settings.getBool('default_hidden', False))
            url = channel.pop('_url', '')
            name = channel.pop('_name', '')
            modified = channel.pop('_modified')
            source = channel.pop('_source', None)
            added = channel.pop('_added', None)

            if hidden:
                continue

            outfile.write(u'\n#EXTINF:-1')
            for key in channel:
                outfile.write(u' {}="{}"'.format(key, channel[key]))

            outfile.write(u',{}\n{}'.format(name, url))

    return merged_path