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()
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))
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
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)
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
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
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)
def call(cmd): log.debug('Subprocess call: {}'.format(cmd)) return subprocess.call(cmd)
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