def list_channels_edit(label): xbmcplugin.setPluginCategory(_handle, label) channels = Channels() channels_list = channels.get_channels_list('number', visible_filter=False) if len(channels_list) > 0: for number in sorted(channels_list.keys()): if channels_list[number]['visible'] == True: list_item = xbmcgui.ListItem(label=str(number) + ' ' + channels_list[number]['name']) else: list_item = xbmcgui.ListItem( label='[COLOR=gray]' + str(number) + ' ' + channels_list[number]['name'] + '[/COLOR]') url = get_url(action='edit_channel', channelKey=encode( channels_list[number]['channelKey'])) list_item.addContextMenuItems([ ('Zvýšit čísla kanálů', encode('RunPlugin(plugin://' + plugin_id + '?action=change_channels_numbers&from_number=' + str(number) + '&direction=increase)')), ('Snížit čísla kanálů', encode('RunPlugin(plugin://' + plugin_id + '?action=change_channels_numbers&from_number=' + str(number) + '&direction=decrease)')), ('Odstranit kanál', encode('RunPlugin(plugin://' + plugin_id + '?action=delete_channel&channelKey=' + quote(encode(channels_list[number]['channelKey'])) + ')')) ]) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def get_listitem_epg_details(list_item, epgId, img, update_from_api=0): if epgId == None or epgId == 'None': list_item.setInfo('video', {'mediatype': 'movie'}) return list_item event = get_epg_details([epgId], update_from_api=update_from_api) cast = [] directors = [] genres = [] list_item.setInfo('video', {'mediatype': 'movie'}) if 'cover' in event and len(event['cover']) > 0: list_item.setArt({ 'poster': 'https://img1.o2tv.cz/' + event['cover'], 'thumb': 'https://img1.o2tv.cz/' + event['cover'], 'icon': 'https://img1.o2tv.cz/' + event['cover'] }) else: list_item.setArt({'thumb': img, 'icon': img}) if 'description' in event and len(event['description']) > 0: list_item.setInfo('video', {'plot': event['description']}) if 'ratings' in event and len(event['ratings']) > 0: for rating, rating_value in event['ratings'].items(): list_item.setRating(rating, round(float(rating_value) / 10, 1)) if 'cast' in event and len(event['cast']) > 0: for person in event['cast']: cast.append(encode(person)) list_item.setInfo('video', {'cast': cast}) if 'directors' in event and len(event['directors']) > 0: for person in event['directors']: directors.append(encode(person)) list_item.setInfo('video', {'director': directors}) if 'year' in event and len(str(event['year'])) > 0: list_item.setInfo('video', {'year': int(event['year'])}) if 'country' in event and len(event['country']) > 0: list_item.setInfo('video', {'country': event['country']}) if 'original' in event and len(event['original']) > 0: list_item.setInfo('video', {'originaltitle': event['original']}) if 'imdb' in event and len(event['imdb']) > 0: list_item.setInfo('video', {'imdbnumber': event['imdb']}) if 'genres' in event and len(event['genres']) > 0: for genre in event['genres']: genres.append(encode(genre)) list_item.setInfo('video', {'genre': genres}) if 'episodeNumber' in event and event['episodeNumber'] != None and int( event['episodeNumber']) > 0: # list_item.setInfo('video', {'mediatype': 'episode', 'episode' : int(event['episodeNumber'])}) list_item.setInfo('video', {'mediatype': 'episode'}) if 'episodeName' in event and event['episodeName'] != None and len( event['episodeName']) > 0: list_item.setInfo('video', {'title': event['episodeName']}) if 'seriesName' in event and event['seriesName'] != None and len( event['seriesName']) > 0: list_item.setInfo('video', {'tvshowtitle': event['seriesName']}) # if 'seasonNumber' in event and event['seasonNumber'] != None and int(event['seasonNumber']) > 0: # list_item.setInfo('video', {'season' : int(event['seasonNumber'])}) return list_item
def load_o2_channels_list(serviceid, list): session = Session() channels = Channels() data = call_o2_api( url= 'https://app.o2tv.cz/sws/subscription/settings/get-user-pref.json?name=nangu.channelListUserChannelNumbers', data=None, header=get_header(session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením seznamu kanálů', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'listUserChannelNumbers' in data and len( data['listUserChannelNumbers']) > 0: for list_name in data['listUserChannelNumbers']: if list == encode(list_name): channels_list = channels.get_channels_list( visible_filter=False) for channel in channels_list: if channel in data['listUserChannelNumbers'][decode(list)]: channels.set_visibility(channel, True) else: channels.set_visibility(channel, False) xbmcgui.Dialog().notification('Sledování O2TV', 'Seznam kanálů byl načtený', xbmcgui.NOTIFICATION_INFO, 5000) else: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením seznamu kanálů', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit()
def edit_channel_group_list_channels(group, label): group = decode(group) xbmcplugin.setPluginCategory(_handle, label) channels_groups = Channels_groups() channels = Channels() channels_list = channels.get_channels_list('number', visible_filter=False) for number in sorted(channels_list.keys()): if not group in channels_groups.groups or not group in channels_groups.channels or not channels_list[ number]['channelKey'] in channels_groups.channels[group]: list_item = xbmcgui.ListItem(label=str(number) + ' ' + channels_list[number]['name']) url = get_url(action='edit_channel_group_add_channel', group=encode(group), channel=encode(channels_list[number]['channelKey'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def list_related(epgId, label): xbmcplugin.setPluginCategory(_handle, label) addon = xbmcaddon.Addon(id=plugin_id) channels = Channels() channels_list = channels.get_channels_list() data = call_o2_api(url='https://api.o2tv.cz/unity/api/v1/programs/' + str(epgId) + '/related/?encodedChannels=' + channels.get_encoded_channels() + '&isFuture=false', data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením kategorie', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'result' in data and len(data['result']) > 0: for event in data['result']: if event['channelKey'] in channels_list: startts = event['start'] / 1000 start = datetime.fromtimestamp(event['start'] / 1000) endts = event['end'] / 1000 end = datetime.fromtimestamp(event['end'] / 1000) epgId = event['epgId'] list_item = xbmcgui.ListItem( label=event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ' | ' + decode(utils.day_translation_short[start.strftime('%w')]) + ' ' + start.strftime('%d.%m %H:%M') + ' - ' + end.strftime('%H:%M') + ')') list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ')' }) list_item = get_listitem_epg_details( list_item, str(event['epgId']), channels_list[event['channelKey']]['logo']) list_item.setProperty('IsPlayable', 'true') list_item.setContentLookup(False) if addon.getSetting('download_streams') == 'true': list_item.addContextMenuItems([ ('Stáhnout', 'RunPlugin(plugin://' + plugin_id + '?action=add_to_queue&epgId=' + str(epgId) + ')') ]) url = get_url(action='play_archiv', channelKey=encode(event['channelKey']), start=startts, end=endts, epgId=epgId) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle) else: xbmcgui.Dialog().notification('Sledování O2TV', 'Žádné pořady nenalezeny', xbmcgui.NOTIFICATION_INFO, 4000)
def list_planning_recordings(label): xbmcplugin.setPluginCategory(_handle, label) channels = Channels() channels_list = channels.get_channels_list('number') for number in sorted(channels_list.keys()): list_item = xbmcgui.ListItem(label=channels_list[number]['name']) if len(channels_list[number]['logo']) > 0: list_item.setArt({ 'thumb': channels_list[number]['logo'], 'icon': channels_list[number]['logo'] }) url = get_url(action='list_rec_days', channelKey=encode(channels_list[number]['channelKey']), label=label + ' / ' + encode(channels_list[number]['name'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle)
def edit_channel_group(group, label): group = decode(group) xbmcplugin.setPluginCategory(_handle, label) channels_groups = Channels_groups() channels = Channels() channels_list = channels.get_channels_list(visible_filter=False) list_item = xbmcgui.ListItem(label='Přidat kanál') url = get_url(action='edit_channel_group_list_channels', group=encode(group), label=encode(group) + ' / Přidat kanál') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) list_item = xbmcgui.ListItem(label='Přidat všechny kanály') url = get_url(action='edit_channel_group_add_all_channels', group=encode(group), label=encode(group) + ' / Přidat kanál') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) if group in channels_groups.channels: for channel in channels_groups.channels[group]: if channel in channels_list: list_item = xbmcgui.ListItem( label=channels_list[channel]['name']) url = get_url(action='edit_channel_group', group=encode(group), label=label) list_item.addContextMenuItems([( 'Smazat kanál', 'RunPlugin(plugin://' + plugin_id + '?action=edit_channel_group_delete_channel&group=' + quote(encode(group)) + '&channel=' + quote(encode(channel)) + ')', )]) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def list_series(epgId, season, label): xbmcplugin.setPluginCategory(_handle, label) params = '' channels = Channels() channels_list = channels.get_channels_list() if int(season) > 0: params = params + '&seasonNumber=' + str(season) data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/programs/' + str(epgId) + '/episodes/?containsAllGenres=false&encodedChannels=' + channels.get_encoded_channels() + '&isFuture=false' + params, data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením kategorie', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() if 'result' in data and len(data['result']) > 0: for event in data['result']: if event['channelKey'] in channels_list: startts = event['start'] / 1000 start = datetime.fromtimestamp(event['start'] / 1000) endts = event['end'] / 1000 end = datetime.fromtimestamp(event['end'] / 1000) epgId = event['epgId'] list_item = xbmcgui.ListItem( label=event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ' | ' + decode(utils.day_translation_short[start.strftime('%w')]) + ' ' + start.strftime('%d.%m %H:%M') + ' - ' + end.strftime('%H:%M') + ')') list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ')' }) list_item = get_listitem_epg_details( list_item, str(event['epgId']), channels_list[event['channelKey']]['logo']) list_item.setProperty('IsPlayable', 'true') list_item.setContentLookup(False) url = get_url(action='play_archiv', channelKey=encode(event['channelKey']), start=startts, end=endts, epgId=epgId) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle)
def download_stream(epgId, url, event): addon = xbmcaddon.Addon() downloads_dir = addon.getSetting('downloads_dir') ffmpeg_bin = addon.getSetting('ffmpeg_bin') xbmcgui.Dialog().notification( 'Sledování O2TV', 'Stahování ' + encode(event['title']) + ' začalo', xbmcgui.NOTIFICATION_INFO, 5000) filename = get_filename(event['title'], event['startTime']) close_db() open_db() current_ts = int(time.mktime(datetime.now().timetuple())) db.execute('UPDATE queue SET downloadts = ? WHERE epgId = ?', [current_ts, epgId]) db.commit() close_db() ffmpeg_params = '-re -y -i ' + str( url ) + ' -f mpegts -mpegts_service_type digital_tv -metadata service_provider=SledovaniO2TV -c:v copy -c:a copy -loglevel error ' + downloads_dir + filename cmd = ffmpeg_bin + ' ' + ffmpeg_params osname = platform.system() xbmc.log(cmd) if osname == 'Windows': subprocess.call(cmd, stdin=None, stdout=None, stderr=None, shell=False, creationflags=0x08000000) else: subprocess.call(cmd, stdin=None, stdout=None, stderr=None, shell=True) xbmcgui.Dialog().notification( 'Sledování O2TV', 'Stahování ' + encode(event['title']) + ' bylo dokončeno', xbmcgui.NOTIFICATION_INFO, 5000) open_db() current_ts = int(time.mktime(datetime.now().timetuple())) db.execute('UPDATE queue SET status = 1, downloadts = ? WHERE epgId = ?', [str(current_ts), str(epgId)]) db.commit()
def list_downloads(label): _handle = int(sys.argv[1]) xbmcplugin.setPluginCategory(_handle, label) open_db() for row in db.execute( 'SELECT epgId, title, startts, endts, status, downloadts FROM queue ORDER BY downloadts DESC' ): epgId = int(row[0]) title = row[1] startts = int(row[2]) endts = int(row[3]) status = int(row[4]) if row[5] != 'null': downloadts = int(row[5]) else: downloadts = None currentts = int(time.mktime(datetime.now().timetuple())) if status == 1: title = encode(title) + ' (100%)' elif status == -1: title = encode(title) + ' (CHYBA)' elif downloadts == None: title = encode(title) + ' (ČEKÁ)' else: pct = float(currentts - downloadts) / (endts - startts) * 100 title = encode(title) + ' (' + str(int(pct)) + '%)' list_item = xbmcgui.ListItem(label=title) list_item.setProperty('IsPlayable', 'false') list_item.setContentLookup(False) list_item.addContextMenuItems([ ('Smazat z fronty', 'RunPlugin(plugin://' + plugin_id + '?action=remove_from_queue&epgId=' + str(epgId) + ')') ]) url = get_url(action='list_downloads', label=label) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False) close_db()
def list_channels_groups(label): xbmcplugin.setPluginCategory(_handle, label) channels_groups = Channels_groups() list_item = xbmcgui.ListItem(label='Nová skupina') url = get_url(action='add_channel_group', label='Nová skupina') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) if channels_groups.selected == None: list_item = xbmcgui.ListItem(label='[B]Všechny kanály[/B]') else: list_item = xbmcgui.ListItem(label='Všechny kanály') url = get_url(action='list_channels_groups', label='Seznam kanálů / Skupiny kanálů') list_item.addContextMenuItems([( 'Vybrat skupinu', 'RunPlugin(plugin://' + plugin_id + '?action=select_channel_group&group=all)', )]) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) for channels_group in channels_groups.groups: if channels_groups.selected == channels_group: list_item = xbmcgui.ListItem(label='[B]' + channels_group + '[/B]') else: list_item = xbmcgui.ListItem(label=channels_group) url = get_url(action='edit_channel_group', group=encode(channels_group), label='Skupiny kanálů / ' + encode(channels_group)) list_item.addContextMenuItems([ ('Vybrat skupinu', 'RunPlugin(plugin://' + plugin_id + '?action=select_channel_group&group=' + quote(encode(channels_group)) + ')'), ('Smazat skupinu', 'RunPlugin(plugin://' + plugin_id + '?action=delete_channel_group&group=' + quote(encode(channels_group)) + ')') ]) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def list_subcategories(category, label): xbmcplugin.setPluginCategory(_handle, label) categories, subcategories, slugs = load_categories() # pylint: disable=unused-variable subcategory_keys = {} for num in subcategories[category].keys(): subcategory_keys.update({int(num): num}) for num in sorted(subcategory_keys.keys()): subcategory = subcategory_keys[num] if subcategories[category][subcategory][ 'type'] == 'programs' and encode( subcategories[category][subcategory]['filter'] ['contentType']) != 'živý přenos': filtr = encode( json.dumps({ 'genres': subcategories[category][subcategory]['filter']['genres'], 'notGenres': subcategories[category][subcategory]['filter'] ['notGenres'], 'containsAllGenres': subcategories[category][subcategory]['filter'] ['containsAllGenres'], 'contentType': subcategories[category][subcategory]['filter'] ['contentType'] })) list_item = xbmcgui.ListItem( label=encode(subcategories[category][subcategory]['name'])) url = get_url( action='list_category', category=encode(subcategories[category][subcategory]['name']), dataSource=subcategories[category][subcategory]['dataSource'], filtr=filtr, label=label + ' / ' + encode(subcategories[category][subcategory]['name'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle)
def edit_channel(channelKey): channelKey = decode(channelKey) channels = Channels() channels_list = channels.get_channels_list(visible_filter=False) new_num = xbmcgui.Dialog().numeric( 0, 'Číslo kanálu', str(channels_list[channelKey]['number'])) if len(new_num) > 0 and int(new_num) > 0: channels_nums = channels.get_channels_list('number', visible_filter=False) if int(new_num) in channels_nums: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Číslo kanálu ' + new_num + ' je použité u kanálu ' + encode(channels_nums[int(new_num)]['name']), xbmcgui.NOTIFICATION_ERROR, 5000) else: channels.set_number(channelKey, new_num)
def future_program(channelKey, day, label): label = label.replace('Nahrávky / Plánování /', '') xbmcplugin.setPluginCategory(_handle, label) channels = Channels() channels_list = channels.get_channels_list() channelKey = decode(channelKey) if int(day) == 0: from_datetime = datetime.now() to_datetime = datetime.combine(date.today(), datetime.max.time()) else: from_datetime = datetime.combine( date.today(), datetime.min.time()) + timedelta(days=int(day)) to_datetime = datetime.combine(from_datetime, datetime.max.time()) from_ts = int(time.mktime(from_datetime.timetuple())) to_ts = int(time.mktime(to_datetime.timetuple())) events = get_epg_ts(channelKey, from_ts, to_ts, 5) for key in sorted(events.keys()): epgId = events[key]['epgId'] start = events[key]['start'] end = events[key]['end'] list_item = xbmcgui.ListItem( label=decode(utils.day_translation_short[start.strftime('%w')]) + ' ' + start.strftime('%d.%m %H:%M') + ' - ' + end.strftime('%H:%M') + ' | ' + events[key]['title']) list_item = get_listitem_epg_details(list_item, str(epgId), channels_list[channelKey]['logo']) list_item.setInfo('video', { 'mediatype': 'movie', 'title': events[key]['title'] }) list_item.setProperty('IsPlayable', 'false') list_item.addContextMenuItems([( 'Přidat nahrávku', 'RunPlugin(plugin://' + plugin_id + '?action=add_recording&channelKey=' + channelKey + '&epgId=' + str(epgId) + ')', )]) url = get_url(action='add_recording', channelKey=encode(channelKey), epgId=epgId) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle)
def add_to_queue(epgId, pvrProgramId): open_db() event = get_epg_details([epgId], update_from_api=1) row = None for row in db.execute('SELECT epgId FROM queue WHERE epgId = ?', [str(epgId)]): xbmcgui.Dialog().notification('Sledování O2TV', 'Pořad už je ve frontě ke stažení!', xbmcgui.NOTIFICATION_ERROR, 5000) close_db() sys.exit() if row == None: db.execute('INSERT INTO queue VALUES (?, ?, ?, ?, ?, ?, ?)', [ epgId, event['title'], event['startTime'], event['endTime'], 0, 'null', pvrProgramId ]) db.commit() xbmcgui.Dialog().notification( 'Sledování O2TV', 'Pořad ' + encode(event['title']) + ' byl přidaný do fronty ke stažení', xbmcgui.NOTIFICATION_INFO, 5000) close_db()
def get_o2_channels_lists(label): xbmcplugin.setPluginCategory(_handle, label) session = Session() for serviceid in session.get_services(): data = call_o2_api( url= 'https://app.o2tv.cz/sws/subscription/settings/get-user-pref.json?name=nangu.channelListUserChannelNumbers', data=None, header=get_header(session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením seznamu kanálů', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'listUserChannelNumbers' in data and len( data['listUserChannelNumbers']) > 0: for list in data['listUserChannelNumbers']: list_item = xbmcgui.ListItem(label=list.replace('user::', '')) url = get_url(action='load_o2_channels_list', serviceid=serviceid, list=encode(list)) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle)
def list_categories(label): xbmcplugin.setPluginCategory(_handle, label) categories, subcategories, slugs = load_categories() # pylint: disable=unused-variable for slug in slugs: if categories[slug]['type'] == 'programs' and 'filter' in categories[ slug]: filtr = encode( json.dumps({ 'genres': categories[slug]['filter']['genres'], 'notGenres': categories[slug]['filter']['notGenres'], 'containsAllGenres': categories[slug]['filter']['containsAllGenres'], 'contentType': categories[slug]['filter']['contentType'] })) list_item = xbmcgui.ListItem( label=encode(categories[slug]['name'])) url = get_url( action='list_category', category=encode(categories[slug]['filter']['contentType']), dataSource=categories[slug]['dataSource'], filtr=filtr, label=label + ' / ' + encode(categories[slug]['name'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) if categories[slug]['type'] == 'list' and 'filter' in categories[slug]: list_item = xbmcgui.ListItem( label=encode(categories[slug]['name'])) url = get_url(action='list_subcategories', category=encode(categories[slug]['filter']['name']), dataSource=categories[slug]['dataSource'], label=label + ' / ' + encode(categories[slug]['name'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle)
def load_categories(): addon = xbmcaddon.Addon() addon_userdata_dir = translatePath(addon.getAddonInfo('profile')) filename = addon_userdata_dir + 'categories.txt' not_found = 0 try: with codecs.open(filename, 'r', encoding='utf-8') as file: for line in file: data = json.loads(line[:-1]) except IOError: not_found = 1 if not_found == 1 or (data and 'valid_to' in data and data['valid_to'] < int(time.time())): slugs = [] invalid_slugs = [] categories = {} subcategories = {} data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/lists/?name=catalogue', data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením kategorií', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'result' in data and len(data['result']) > 0: for category in data['result']: if 'slug' in category and len(category['slug']) > 0: slugs.append(category['slug']) for slug in slugs: data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/lists/slug/?slug=' + slug, data=None, header=get_header_unity()) if 'err' in data: invalid_slugs.append(slug) else: if 'name' in data and len(data['name']) > 0: categories.update({ slug: { 'name': data['name'], 'type': data['type'], 'filter': data['filter'], 'dataSource': data['dataSource'] } }) for slug in invalid_slugs: slugs.remove(slug) for slug in slugs: if categories[slug]['type'] == 'list': data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/lists/?name=' + encode(categories[slug]['filter']['name']), data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém s načtením kategorií', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() if 'result' in data and len(data['result']) > 0: cnt = 0 subcategory = {} for category in data['result']: subcategory.update({ cnt: { 'name': category['name'], 'type': category['type'], 'filter': category['filter'], 'dataSource': category['dataSource'] } }) cnt = cnt + 1 subcategories.update( {categories[slug]['filter']['name']: subcategory}) try: with codecs.open(filename, 'w', encoding='utf-8') as file: data = json.dumps({ 'categories': categories, 'subcategories': subcategories, 'slugs': slugs, 'valid_to': int(time.time()) + 60 * 60 * 24 }) file.write('%s\n' % data) except IOError: xbmc.log('Chyba uložení kategorií') else: categories = data['categories'] subcategories = data['subcategories'] slugs = data['slugs'] return categories, subcategories, slugs
def list_category(category, dataSource, filtr, page, label): xbmcplugin.setPluginCategory(_handle, label) addon = xbmcaddon.Addon() page_limit = int(addon.getSetting('category_pagesize')) filtr = json.loads(filtr) params = '' genres = [] nongenres = [] for genre in filtr['genres']: if len(genre) > 0: params = params + '&genres=' + quote_plus(encode(genre)) genres.append(genre) for nongenre in filtr['notGenres']: if len(nongenre) > 0: params = params + '¬Genres=' + quote_plus(encode(nongenre)) nongenres.append(nongenre) contentType = filtr['contentType'] channels = Channels() channels_list = channels.get_channels_list() events = {} data = call_o2_api( url='https://api.o2tv.cz' + dataSource + '?containsAllGenres=' + str(filtr['containsAllGenres']).lower() + '&contentType=' + contentType + params + '&encodedChannels=' + channels.get_encoded_channels() + '&sort=-o2rating&grouped=true&isFuture=false&limit=500&offset=0', data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s načtením kategorie', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'result' in data and len(data['result']) > 0: num = 0 cnt = 0 characters = [] for event in data['result']: cnt = cnt + 1 if addon.getSetting('categories_sorting') == 'ratingu': events.update({num: event}) num = num + 1 else: events.update({remove_diacritics(event['name']): event}) if remove_diacritics( event['name'][:1].upper()) not in characters: characters.append( remove_diacritics(event['name'][:1].upper())) if addon.getSetting( 'categories_sorting' ) == 'názvu' and page is None and page_limit > 0 and len( events) > page_limit: characters.sort() for character in characters: list_item = xbmcgui.ListItem(label=character) url = get_url(action='list_category', category=contentType, dataSource=dataSource, filtr=json.dumps(filtr), page=encode(character), label=label + ' / ' + encode(character.decode('utf-8'))) xbmcplugin.addDirectoryItem(_handle, url, list_item, True) else: if addon.getSetting( 'categories_sorting') == 'ratingu' and page_limit > 0: if page is None: page = 1 startitem = (int(page) - 1) * page_limit cnt = 0 for key in sorted(events.keys()): if page is None or page_limit == 0 or ( page is not None and addon.getSetting('categories_sorting') == 'názvu' and remove_diacritics(events[key]['name'][:1].upper()) == page.encode('utf-8') ) or (page is not None and addon.getSetting('categories_sorting') == 'ratingu' and cnt >= startitem and cnt < startitem + page_limit): event = events[key] startts = event['start'] / 1000 start = datetime.fromtimestamp(event['start'] / 1000) endts = event['end'] / 1000 end = datetime.fromtimestamp(event['end'] / 1000) epgId = event['epgId'] isSeries = 0 if event['channelKey'] in channels_list: if 'seriesInfo' in event and 'seriesName' in event[ 'seriesInfo'] and len( event['seriesInfo']['seriesName']) > 0: isSeries = 1 event['name'] = event['seriesInfo']['seriesName'] if 'seasonNumber' in event['seriesInfo']: event['name'] = event[ 'name'] # + ' ['+ str(event['seriesInfo']['seasonNumber']) + ']' list_item = xbmcgui.ListItem( label=event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ')') else: list_item = xbmcgui.ListItem( label=event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ' | ' + decode(utils.day_translation_short[ start.strftime('%w')]) + ' ' + start.strftime('%d.%m %H:%M') + ' - ' + end.strftime('%H:%M') + ')') cast = [] directors = [] genres = [] list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': event['name'] + ' (' + channels_list[event['channelKey']]['name'] + ')' }) if 'images' in event and len(event['images']) > 0: list_item.setArt({ 'poster': 'https://img1.o2tv.cz/' + event['images'][0]['cover'], 'thumb': 'https://img1.o2tv.cz/' + event['images'][0]['cover'], 'icon': 'https://img1.o2tv.cz/' + event['images'][0]['cover'] }) if 'longDescription' in event and len( event['longDescription']) > 0: list_item.setInfo( 'video', {'plot': event['longDescription']}) if 'ratings' in event and len(event['ratings']) > 0: for rating, rating_value in event['ratings'].items( ): list_item.setRating(rating, int(rating_value) / 10) if 'castAndCrew' in event and len( event['castAndCrew'] ) > 0 and 'cast' in event['castAndCrew'] and len( event['castAndCrew']['cast']) > 0: for person in event['castAndCrew']['cast']: cast.append(encode(person['name'])) list_item.setInfo('video', {'cast': cast}) if 'castAndCrew' in event and len( event['castAndCrew'] ) > 0 and 'directors' in event['castAndCrew'] and len( event['castAndCrew']['directors']) > 0: for person in event['castAndCrew']['directors']: directors.append(encode(person['name'])) list_item.setInfo('video', {'director': directors}) if 'origin' in event and len(event['origin']) > 0: if 'year' in event['origin'] and len( str(event['origin']['year'])) > 0: list_item.setInfo( 'video', {'year': event['origin']['year']}) if 'country' in event['origin'] and len( event['origin']['country']) > 0: list_item.setInfo('video', { 'country': event['origin']['country']['name'] }) if 'origName' in event and len(event['origName']) > 0: list_item.setInfo( 'video', {'originaltitle': event['origName']}) if 'ext' in event and len( event['ext']) > 0 and 'imdbId' in event[ 'ext'] and len(event['ext']['imdbId']) > 0: list_item.setInfo( 'video', {'imdbnumber': event['ext']['imdbId']}) if 'genreInfo' in event and len( event['genreInfo'] ) > 0 and 'genres' in event['genreInfo'] and len( event['genreInfo']['genres']) > 0: for genre in event['genreInfo']['genres']: genres.append(encode(genre['name'])) list_item.setInfo('video', {'genre': genres}) menus = [ ('Související pořady', 'Container.Update(plugin://' + plugin_id + '?action=list_related&epgId=' + str(epgId) + '&label=Související / ' + encode(event['name']) + ')'), ('Vysílání pořadu', 'Container.Update(plugin://' + plugin_id + '?action=list_same&epgId=' + str(epgId) + '&label=' + encode(event['name']) + ')'), ('Přidat nahrávku', 'RunPlugin(plugin://' + plugin_id + '?action=add_recording&channelKey=' + event['channelKey'] + '&epgId=' + str(epgId) + ')') ] if addon.getSetting('download_streams') == 'true': menus.append( ('Stáhnout', 'RunPlugin(plugin://' + plugin_id + '?action=add_to_queue&epgId=' + str(epgId) + ')')) list_item.addContextMenuItems(menus) if isSeries == 0: list_item.setProperty('IsPlayable', 'true') list_item.setContentLookup(False) url = get_url(action='play_archiv', channelKey=encode( event['channelKey']), start=startts, end=endts, epgId=epgId) xbmcplugin.addDirectoryItem( _handle, url, list_item, False) else: if 'seasonNumber' in event['seriesInfo'] and int( event['seriesInfo']['seasonNumber']) > 0: season = int( event['seriesInfo']['seasonNumber']) else: season = -1 list_item.setProperty('IsPlayable', 'false') url = get_url(action='list_series', epgId=epgId, season=season, label=encode(event['name'])) xbmcplugin.addDirectoryItem( _handle, url, list_item, True) cnt = cnt + 1 if page is not None and addon.getSetting( 'categories_sorting' ) == 'ratingu' and int(page) * page_limit <= cnt: list_item = xbmcgui.ListItem(label='další strana') url = get_url(action='list_category', category=contentType, dataSource=dataSource, filtr=json.dumps(filtr), page=int(page) + 1, label=label) list_item.setProperty('IsPlayable', 'false') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle)
def list_devices(label): xbmcplugin.setPluginCategory(_handle, label) session = Session() for serviceid in session.get_services(): data = call_o2_api(url='https://api.o2tv.cz/unity/api/v1/devices/', data=None, header=get_header_unity( session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém při zjištování spárovaných zařízení', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() if 'pairedDeviceAddLimit' in data and 'sessionLimit' in data and 'result' in data: list_item = xbmcgui.ListItem( label='Limit souběžných přehrávání: ' + str(int(data['sessionLimit']))) xbmcplugin.addDirectoryItem(_handle, None, list_item, False) else: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém při zjištování spárovaných zařízení', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() data = call_o2_api( url= 'https://app.o2tv.cz/sws/subscription/settings/subscription-configuration.json', data=None, header=get_header(session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém při zjištování spárovaných zařízení', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() if 'pairedDevicesLimit' in data and 'pairedDevices' in data: list_item = xbmcgui.ListItem(label='Spárovaných zařízení: ' + str(len(data['pairedDevices'])) + '/' + str(int(data['pairedDevicesLimit']))) xbmcplugin.addDirectoryItem(_handle, None, list_item, False) if len(data['pairedDevices']) > 0: devices = sorted(data['pairedDevices'], key=lambda k: k['lastLoginTimestamp']) for device in devices: list_item = xbmcgui.ListItem( label=device['deviceName'] + ' (' + str(device['deviceId']) + ') - ' + datetime.fromtimestamp(device['lastLoginTimestamp'] / 1000).strftime('%d.%m.%Y') + ' z ' + device['lastLoginIpAddress']) list_item.addContextMenuItems([( 'Smazat zařízení', 'RunPlugin(plugin://' + plugin_id + '?action=unpair_device&deviceId=' + quote(encode(str(device['deviceId']))) + '&deviceName=' + quote(encode(device['deviceName'])) + '&serviceid=' + serviceid + ')', )]) xbmcplugin.addDirectoryItem(_handle, None, list_item, False) else: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém při zjištování spárovaných zařízení', xbmcgui.NOTIFICATION_ERROR, 4000) sys.exit() xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def list_recordings(label): xbmcplugin.setPluginCategory(_handle, label) addon = xbmcaddon.Addon() channels = Channels() channels_list = channels.get_channels_list(visible_filter=False) session = Session() recordings = {} list_item = xbmcgui.ListItem(label='Plánování nahrávek') url = get_url(action='list_planning_recordings', label=label + ' / ' + 'Plánování') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) list_item = xbmcgui.ListItem(label='Naplánované nahrávky') url = get_url(action='list_future_recordings', label=label + ' / ' + 'Naplánované nahrávky') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) for serviceid in session.get_services(): data = call_o2_api(url='https://api.o2tv.cz/unity/api/v1/recordings/', data=None, header=get_header_unity( session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém s načtením nahrávek, zkuste to znovu', xbmcgui.NOTIFICATION_ERROR, 6000) if 'result' in data and len(data['result']) > 0: for program in data['result']: if program['state'] == 'DONE': recordings.update({ program['program']['start'] + random.randint(0, 100): { 'pvrProgramId': program['pvrProgramId'], 'name': program['program']['name'], 'channelKey': program['program']['channelKey'], 'start': decode(utils.day_translation_short[ datetime.fromtimestamp( program['program']['start'] / 1000).strftime('%w')]) + ' ' + datetime.fromtimestamp( program['program']['start'] / 1000).strftime('%d.%m %H:%M'), 'end': datetime.fromtimestamp(program['program']['end'] / 1000).strftime('%H:%M'), 'epgId': program['program']['epgId'] } }) for recording in sorted(recordings.keys(), reverse=True): if recordings[recording]['channelKey'] in channels_list: list_item = xbmcgui.ListItem( label=recordings[recording]['name'] + ' (' + recordings[recording]['channelKey'] + ' | ' + recordings[recording]['start'] + ' - ' + recordings[recording]['end'] + ')') list_item.setProperty('IsPlayable', 'true') list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': recordings[recording]['name'] + ' (' + recordings[recording]['channelKey'] + ')' }) list_item = get_listitem_epg_details( list_item, recordings[recording]['epgId'], channels_list[recordings[recording]['channelKey']]['logo']) list_item.setContentLookup(False) menus = [('Smazat nahrávku', 'RunPlugin(plugin://' + plugin_id + '?action=delete_recording&channelKey=' + recordings[recording]['channelKey'] + '&pvrProgramId=' + str(recordings[recording]['pvrProgramId']) + ')')] if addon.getSetting('download_streams') == 'true': menus.append( ('Stáhnout', 'RunPlugin(plugin://' + plugin_id + '?action=add_to_queue&epgId=' + str(recordings[recording]['epgId']) + '&pvrProgramId=' + str(recordings[recording]['pvrProgramId']) + ')')) list_item.addContextMenuItems(menus) url = get_url(action='play_recording', channelKey=encode( recordings[recording]['channelKey']), pvrProgramId=recordings[recording]['pvrProgramId'], title=encode(recordings[recording]['name'])) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def generate_playlist(output_file=''): addon = xbmcaddon.Addon() if addon.getSetting('output_dir') is None or len( addon.getSetting('output_dir')) == 0: xbmcgui.Dialog().notification('Sledování O2TV', 'Nastav adresář pro playlist!', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() channels = Channels() channels_list = channels.get_channels_list('number') if len(output_file) > 0: filename = output_file else: filename = addon.getSetting('output_dir') + 'playlist.m3u' if save_file_test(epg=0) == 0: xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba při uložení playlistu', xbmcgui.NOTIFICATION_ERROR, 5000) return try: file = xbmcvfs.File(filename, 'w') if file == None: xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba při uložení playlistu', xbmcgui.NOTIFICATION_ERROR, 5000) else: file.write(bytearray(('#EXTM3U\n').encode('utf-8'))) for number in sorted(channels_list.keys()): logo = channels_list[number]['logo'] if addon.getSetting('add_channel_numbers') == 'true': if addon.getSetting('catchup_mode') == 'default': line = '#EXTINF:-1 catchup="default" catchup-days="7" catchup-source="plugin://plugin.video.archivo2tv/?action=get_stream_url&channelKey=' + quote( encode(channels_list[number]['channelKey']) ) + '&catchup_start_ts={utc}&catchup_end_ts={utcend}" tvg-chno="' + str( number ) + '" tvg-id="' + channels_list[number][ 'name'] + '" tvh-epg="0" tvg-logo="' + logo + '",' + channels_list[ number]['name'] else: line = '#EXTINF:-1 catchup="append" catchup-days="7" catchup-source="&catchup_start_ts={utc}&catchup_end_ts={utcend}" tvg-chno="' + str( number ) + '" tvg-id="' + channels_list[number][ 'name'] + '" tvh-epg="0" tvg-logo="' + logo + '",' + channels_list[ number]['name'] else: if addon.getSetting('catchup_mode') == 'default': line = '#EXTINF:-1 catchup="default" catchup-days="7" catchup-source="plugin://plugin.video.archivo2tv/?action=get_stream_url&channelKey=' + quote( encode(channels_list[number]['channelKey']) ) + '&catchup_start_ts={utc}&catchup_end_ts={utcend}" tvg-id="' + channels_list[ number][ 'name'] + '" tvh-epg="0" tvg-logo="' + logo + '",' + channels_list[ number]['name'] else: line = '#EXTINF:-1 catchup="append" catchup-days="7" catchup-source="&catchup_start_ts={utc}&catchup_end_ts={utcend}" tvg-id="' + channels_list[ number][ 'name'] + '" tvh-epg="0" tvg-logo="' + logo + '",' + channels_list[ number]['name'] file.write(bytearray((line + '\n').encode('utf-8'))) line = 'plugin://' + plugin_id + '/?action=get_stream_url&channelKey=' + quote( encode(channels_list[number]['channelKey'])) if addon.getSetting('iptvsc_timeshift') == 'true': file.write( bytearray( ('#KODIPROP:inputstream=inputstream.ffmpegdirect\n' ).encode('utf-8'))) file.write( bytearray(( '#KODIPROP:inputstream.ffmpegdirect.stream_mode=timeshift\n' ).encode('utf-8'))) file.write( bytearray(( '#KODIPROP:inputstream.ffmpegdirect.is_realtime_stream=true\n' ).encode('utf-8'))) file.write( bytearray(('#KODIPROP:mimetype=video/mp2t\n' ).encode('utf-8'))) file.write(bytearray((line + '\n').encode('utf-8'))) file.close() xbmcgui.Dialog().notification('Sledování O2TV', 'Playlist byl uložený', xbmcgui.NOTIFICATION_INFO, 5000) except Exception: file.close() xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba při uložení playlistu', xbmcgui.NOTIFICATION_ERROR, 5000)
def iptv_sc_play(channelName, startdatetime, epg): epgId = -1 addon = xbmcaddon.Addon() channelName = decode(channelName) if len(startdatetime) > 0: from_ts = int( time.mktime(time.strptime(startdatetime, '%d.%m.%Y %H:%M'))) else: from_ts = int(time.mktime(datetime.now().timetuple())) channels = Channels() channels_list = channels.get_channels_list('name', visible_filter=False) if channelName not in channels_list: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Kanál přehrávaný z IPTV SC nebyl nalezený!', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() channelKey = channels_list[channelName]['channelKey'] if from_ts > int(time.mktime(datetime.now().timetuple())): xbmcgui.Dialog().notification('Sledování O2TV', 'Nelze přehrát budoucí pořad!', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() else: event = get_epgId_iptvsc(channelName, channelKey, from_ts) epgId = event['epgId'] if epgId > 0: startts = event['start'] start = datetime.fromtimestamp(event['start']) endts = event['end'] end = datetime.fromtimestamp(event['end']) epgId = event['epgId'] title = decode( utils.day_translation_short[start.strftime('%w')] ) + ' ' + start.strftime('%d.%m %H:%M') + ' - ' + end.strftime( '%H:%M') + ' | ' + event['title'] if int(epgId) > 0: if int(endts) < int(time.mktime(datetime.now().timetuple())): play_video(type='archiv_iptv', channelKey=encode(channelKey), start=startts, end=endts, epgId=epgId, title=title) else: if epg == 1: play_video(type='live_iptv_epg', channelKey=encode(channelKey), start=None, end=None, epgId=None, title=None) else: play_video(type='live_iptv', channelKey=encode(channelKey), start=None, end=None, epgId=None, title=None) else: if len(startdatetime) == 0: play_video(type='live_iptv', channelKey=encode(channelKey), start=None, end=None, epgId=None, title=None) else: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Pořad u O2 nenalezen! Používáte EPG z doplňku Sledování O2TV?', xbmcgui.NOTIFICATION_ERROR, 10000) sys.exit()
def load_epg_details(): global db events_detailed_data = {} try: url = 'https://api.o2tv.cz/unity/api/v1/epg/' data = call_o2_api(url=url, data=None, header=get_header_unity()) if 'err' in data: xbmc.log('Chyba API O2 při načítání detailních dat pro EPG!') sys.exit() if 'result' in data and len( data['result']) > 0 and 'count' in data and data['count'] > 0: offset = 0 step = 50 cnt = data['count'] for offset in range(0, cnt + step, step): url = 'https://api.o2tv.cz/unity/api/v1/epg/?offset=' + str( offset) data = call_o2_api(url=url, data=None, header=get_header_unity()) if 'err' in data: xbmc.log( 'Chyba API O2 při načítání detailních dat pro EPG!') sys.exit() if 'result' in data and len(data['result']) > 0: for event in data['result']: cover = '' description = '' ratings = {} cast = [] directors = [] year = '' country = '' original = '' imdb = '' genres = [] episodeNumber = -1 episodeName = '' seasonNumber = -1 episodesInSeason = -1 seasonName = '' seriesName = '' contentType = '' if 'images' in event and len( event['images'] ) > 0 and 'cover' in event['images'][0]: cover = event['images'][0]['cover'] elif 'picture' in event and len(event['picture']) > 0: cover = event['picture'] if 'longDescription' in event and len( event['longDescription']) > 0: description = event['longDescription'] elif 'shortDescription' in event and len( event['shortDescription']) > 0: description = event['shortDescription'] if 'ratings' in event and len(event['ratings']) > 0: for rating, rating_value in event['ratings'].items( ): ratings.update({rating: int(rating_value)}) if 'castAndCrew' in event and len( event['castAndCrew'] ) > 0 and 'cast' in event['castAndCrew'] and len( event['castAndCrew']['cast']) > 0: for person in event['castAndCrew']['cast']: cast.append(encode(person['name'])) if 'castAndCrew' in event and len( event['castAndCrew'] ) > 0 and 'directors' in event['castAndCrew'] and len( event['castAndCrew']['directors']) > 0: for person in event['castAndCrew']['directors']: directors.append(encode(person['name'])) if 'origin' in event and len(event['origin']) > 0: if 'year' in event['origin'] and len( str(event['origin']['year'])) > 0: year = event['origin']['year'] if 'country' in event['origin'] and len( event['origin']['country']) > 0: country = event['origin']['country']['name'] if 'origName' in event and len(event['origName']) > 0: original = event['origName'] if 'ext' in event and len( event['ext']) > 0 and 'imdbId' in event[ 'ext'] and len(event['ext']['imdbId']) > 0: imdb = event['ext']['imdbId'] if 'genreInfo' in event and len( event['genreInfo'] ) > 0 and 'genres' in event['genreInfo'] and len( event['genreInfo']['genres']) > 0: for genre in event['genreInfo']['genres']: genres.append(encode(genre['name'])) if 'seriesInfo' in event: if 'episodeNumber' in event['seriesInfo'] and len( str(event['seriesInfo']['episodeNumber']) ) > 0 and int( event['seriesInfo']['episodeNumber']) > 0: episodeNumber = int( event['seriesInfo']['episodeNumber']) if 'episodeName' in event['seriesInfo'] and len( event['seriesInfo']['episodeName']) > 0: episodeName = event['seriesInfo'][ 'episodeName'] if 'seasonNumber' in event['seriesInfo'] and len( str(event['seriesInfo']['seasonNumber']) ) > 0 and int( event['seriesInfo']['seasonNumber']) > 0: seasonNumber = int( event['seriesInfo']['seasonNumber']) if 'episodesInSeason' in event[ 'seriesInfo'] and len( str(event['seriesInfo'] ['episodesInSeason'])) > 0 and int( event['seriesInfo'] ['episodesInSeason']) > 0: episodesInSeason = int( event['seriesInfo']['episodesInSeason']) if 'seasonName' in event['seriesInfo'] and len( event['seriesInfo']['seasonName']) > 0: seasonName = event['seriesInfo']['seasonName'] if 'seriesName' in event['seriesInfo'] and len( event['seriesInfo']['seriesName']) > 0: seriesName = event['seriesInfo']['seriesName'] if 'contentType' in event and len( event['contentType']) > 0: contentType = event['contentType'] events_detailed_data.update({ event['epgId']: { 'cover': cover, 'description': description, 'ratings': ratings, 'cast': cast, 'directors': directors, 'year': year, 'country': country, 'original': original, 'genres': genres, 'imdb': imdb, 'episodeNumber': episodeNumber, 'episodeName': episodeName, 'seasonNumber': seasonNumber, 'episodesInSeason': episodesInSeason, 'seasonName': seasonName, 'seriesName': seriesName, 'contentType': contentType } }) cnt = 0 open_db() for epgId in events_detailed_data.keys(): row = None for row in db.execute('SELECT * FROM epg WHERE epgId = ?', [epgId]): event = row if row: row = None for row in db.execute( 'SELECT * FROM epg_details WHERE epgId = ?', [epgId]): event = row if not row: cnt = cnt + 1 db.execute( 'INSERT INTO epg_details VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (epgId, events_detailed_data[epgId]['cover'], events_detailed_data[epgId]['description'], json.dumps(events_detailed_data[epgId]['ratings']), json.dumps(events_detailed_data[epgId]['cast']), json.dumps(events_detailed_data[epgId]['directors']), events_detailed_data[epgId]['year'], events_detailed_data[epgId]['country'], events_detailed_data[epgId]['original'], json.dumps(events_detailed_data[epgId]['genres']), events_detailed_data[epgId]['imdb'], events_detailed_data[epgId]['episodeNumber'], events_detailed_data[epgId]['episodeName'], events_detailed_data[epgId]['seasonNumber'], events_detailed_data[epgId]['episodesInSeason'], events_detailed_data[epgId]['seasonName'], events_detailed_data[epgId]['seriesName'], events_detailed_data[epgId]['contentType'])) db.commit() close_db() xbmc.log('INSERTED epg_details: ' + str(cnt)) except URLError: xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba API O2 při načítání EPG!', xbmcgui.NOTIFICATION_WARNING, 5000) xbmc.log('Error getting EPG data') pass
def list_program(channelKey, day_min, label): label = label.replace('Archiv /', '') xbmcplugin.setPluginCategory(_handle, label) addon = xbmcaddon.Addon() channelKey = decode(channelKey) channels = Channels() channels_list = channels.get_channels_list() if int(day_min) == 0: from_datetime = datetime.combine(date.today(), datetime.min.time()) to_datetime = datetime.now() else: from_datetime = datetime.combine( date.today(), datetime.min.time()) - timedelta(days=int(day_min)) to_datetime = datetime.combine(from_datetime, datetime.max.time()) from_ts = int(time.mktime(from_datetime.timetuple())) to_ts = int(time.mktime(to_datetime.timetuple())) events = {} events = get_epg_ts(channelKey, from_ts, to_ts, 8) if addon.getSetting('archive_reverse_sort') == "true": archive_reverse = True else: archive_reverse = False for key in sorted(events.keys(), reverse=archive_reverse): if int(events[key]['endts']) > int( time.mktime(datetime.now().timetuple())) - 60 * 60 * 24 * 7: list_item = xbmcgui.ListItem( label=decode(utils.day_translation_short[ events[key]['start'].strftime('%w')]) + ' ' + events[key]['start'].strftime('%d.%m %H:%M') + ' - ' + events[key]['end'].strftime('%H:%M') + ' | ' + events[key]['title']) list_item.setInfo('video', { 'mediatype': 'movie', 'title': events[key]['title'] }) list_item = get_listitem_epg_details( list_item, str(events[key]['epgId']), channels_list[channelKey]['logo']) list_item.setProperty('IsPlayable', 'true') list_item.setContentLookup(False) menus = [ ('Přidat nahrávku', 'RunPlugin(plugin://' + plugin_id + '?action=add_recording&channelKey=' + channelKey + '&epgId=' + str(events[key]['epgId']) + ')'), ('Související pořady', 'Container.Update(plugin://' + plugin_id + '?action=list_related&epgId=' + str(events[key]['epgId']) + '&label=Související / ' + encode(events[key]['title']) + ')'), ('Vysílání pořadu', 'Container.Update(plugin://' + plugin_id + '?action=list_same&epgId=' + str(events[key]['epgId']) + '&label=' + encode(events[key]['title']) + ')') ] if addon.getSetting('download_streams') == 'true': menus.append(('Stáhnout', 'RunPlugin(plugin://' + plugin_id + '?action=add_to_queue&epgId=' + str(events[key]['epgId']) + ')')) list_item.addContextMenuItems(menus) url = get_url(action='play_archiv', channelKey=encode(channelKey), start=events[key]['startts'], end=events[key]['endts'], epgId=events[key]['epgId']) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def load_epg_ts(channelKeys, from_ts, to_ts): global db open_db(check=1) close_db() events_data = {} params = '' for channelKey in channelKeys: params = params + ('&channelKey=' + quote(encode(channelKey))) try: url = 'https://api.o2tv.cz/unity/api/v1/epg/depr/?forceLimit=true&limit=500' + params + '&from=' + str( from_ts * 1000) + '&to=' + str(to_ts * 1000) print(url) data = call_o2_api(url=url, data=None, header=get_header_unity()) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba API O2 při načítání EPG!', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'epg' in data and len( data['epg']) > 0 and 'items' in data['epg'] and len( data['epg']['items']) > 0: for channel in data['epg']['items']: for event in channel['programs']: events_data.update({ event['epgId']: { 'startTime': int(event['start'] / 1000), 'endTime': int(event['end'] / 1000), 'channel': channel['channel']['name'], 'title': event['name'], 'availableTo': int(event['availableTo'] / 1000) } }) cnt = 0 open_db() for epgId in events_data.keys(): row = None for row in db.execute('SELECT * FROM epg WHERE epgId = ?', [epgId]): event = row startTime = int(row[1]) endTime = int(row[2]) channel = row[3] title = row[4] availableTo = int(row[5]) if startTime != events_data[epgId][ 'startTime'] or endTime != events_data[epgId][ 'endTime'] or channel != events_data[epgId][ 'channel'] or title != events_data[epgId][ 'title'] or availableTo != events_data[ epgId]['availableTo']: db.execute( 'UPDATE epg SET startTime = ?, endTime = ?, channel = ?, title = ?, availableTo = ? WHERE epgId = ?', (events_data[epgId]['startTime'], events_data[epgId]['endTime'], events_data[epgId]['channel'], events_data[epgId]['title'], events_data[epgId]['availableTo'], epgId)) if not row: cnt = cnt + 1 db.execute('INSERT INTO epg VALUES(?, ?, ?, ?, ?, ?)', (epgId, events_data[epgId]['startTime'], events_data[epgId]['endTime'], events_data[epgId]['channel'], events_data[epgId]['title'], events_data[epgId]['availableTo'])) db.commit() close_db() xbmc.log('INSERTED epg: ' + str(cnt)) except URLError: xbmc.log('Error getting EPG data') xbmcgui.Dialog().notification('Sledování O2TV', 'Chyba API O2 při načítání EPG!', xbmcgui.NOTIFICATION_WARNING, 5000) pass
def play_video(type, channelKey, start, end, epgId, title): addon = xbmcaddon.Addon() session = Session() channelKey = decode(channelKey) channels = Channels() channels_list = channels.get_channels_list(visible_filter=False) header_unity = get_header_unity( session.get_service(channels_list[channelKey]['serviceid'])) header = get_header( session.get_service(channels_list[channelKey]['serviceid'])) if 'serviceid' not in channels_list[channelKey] or len( channels_list[channelKey]['serviceid']) == 0: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Pravděpodobně neaktivní kanál. Zkuste reset kanálů.', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() subscription = session.get_service( channels_list[channelKey]['serviceid'])['subscription'] if addon.getSetting('select_resolution') == 'true' and addon.getSetting( 'stream_type') == 'HLS' and addon.getSetting('only_sd') != 'true': resolution = xbmcgui.Dialog().select('Rozlišení', ['HD', 'SD'], preselect=0) else: resolution = -1 if addon.getSetting('stream_type') == 'MPEG-DASH': stream_type = 'DASH' else: stream_type = 'HLS' force_mpeg_dash = 0 if addon.getSetting('stream_type') == 'HLS' and xbmc.getCondVisibility( 'System.HasAddon(inputstream.adaptive)') and ( type == 'live_iptv' or type == 'live_iptv_epg' ) and addon.getSetting('force_mpeg_dash') == 'true': stream_type = 'DASH' force_mpeg_dash = 1 if type == 'live' or type == 'live_iptv' or type == 'live_iptv_epg': startts = 0 channels_details = get_epg_live(len(channels_list.keys())) if channels_list[channelKey]['name'] in channels_details: without_details = 0 else: without_details = 1 if channelKey in channels_list and without_details == 0: data = channels_details[channels_list[channelKey]['name']] start = data['start'] startts = int(time.mktime(start.timetuple())) end = data['end'] epgId = str(data['epgId']) if addon.getSetting('stream_type') == 'MPEG-DASH-web': if type == 'archiv' or type == 'archiv_iptv': data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/programs/' + str(epgId) + '/playlist/', data=None, header=header_unity) if type == 'live' or type == 'live_iptv' or type == 'live_iptv_epg': data = call_o2_api( url= 'https://api.o2tv.cz/unity/api/v1/channels/playlist/?channelKey=' + quote(channelKey), data=None, header=header_unity) if type == 'recording': data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/recordings/' + str(epgId) + '/playlist/', data=None, header=header_unity) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s přehráním streamu', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if 'playlist' in data and len( data['playlist']) > 0 and 'streamUrls' in data['playlist'][ 0] and 'main' in data['playlist'][0]['streamUrls'] and len( data['playlist'][0]['streamUrls']['main']) > 0: if 'timeshift' in data['playlist'][0]['streamUrls']: url = data['playlist'][0]['streamUrls']['timeshift'] else: url = data['playlist'][0]['streamUrls']['main'] request = Request(url=url, data=None, headers=header) response = urlopen(request) url = response.geturl() else: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s přehráním streamu', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() else: if type == 'archiv' or type == 'archiv_iptv': start = int(float(start) * 1000) end = int(float(end) * 1000) post = { 'serviceType': 'TIMESHIFT_TV', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'channelKey': encode(channelKey), 'fromTimestamp': str(start), 'toTimestamp': str(end + (int(addon.getSetting('offset')) * 60 * 1000)), 'id': epgId, 'encryptionType': 'NONE' } if type == 'live' or type == 'live_iptv' or type == 'live_iptv_epg': if (addon.getSetting('stream_type') == 'MPEG-DASH' or force_mpeg_dash == 1 ) and startts > 0 and addon.getSetting('startover') == 'true': startts = int(float(startts) * 1000 - 300000) post = { 'serviceType': 'STARTOVER_TV', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'channelKey': encode(channelKey), 'fromTimestamp': startts, 'encryptionType': 'NONE' } else: post = { 'serviceType': 'LIVE_TV', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'channelKey': encode(channelKey), 'encryptionType': 'NONE' } if type == 'recording': post = { 'serviceType': 'NPVR', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'contentId': epgId, 'encryptionType': 'NONE' } if addon.getSetting( 'stream_type') != 'MPEG-DASH' and force_mpeg_dash == 0 and ( addon.getSetting('only_sd') == 'true' or resolution == 1): post.update({'resolution': 'SD'}) data = call_o2_api( url='https://app.o2tv.cz/sws/server/streaming/uris.json', data=post, header=header) if 'err' in data: if data['err'] == 'Not Found': post = { 'serviceType': 'LIVE_TV', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'channelKey': encode(channelKey), 'encryptionType': 'NONE' } data = call_o2_api( url='https://app.o2tv.cz/sws/server/streaming/uris.json', data=post, header=header) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém s přehráním streamu', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() else: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s přehráním streamu', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() url = '' if 'uris' in data and len( data['uris']) > 0 and 'uri' in data['uris'][0] and len( data['uris'][0]['uri']) > 0: for uris in data['uris']: print(uris) if addon.getSetting( 'only_sd' ) != 'true' and resolution != 1 and uris['resolution'] == 'HD': url = uris['uri'] if (addon.getSetting('only_sd') == 'true' or resolution == 1) and uris['resolution'] == 'SD': url = uris['uri'] if url == '': url = data['uris'][0]['uri'] if addon.getSetting( 'stream_type') == 'MPEG-DASH' or force_mpeg_dash == 1: request = Request(url=url, data=None, headers=header) response = urlopen(request) url = response.geturl().replace('http:', 'https:').replace( ':80/', ':443/') else: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s přehráním streamu', xbmcgui.NOTIFICATION_ERROR, 5000) sys.exit() if type == 'live_iptv' or type == 'live_iptv_epg': list_item = xbmcgui.ListItem(path=url) list_item = get_listitem_epg_details(list_item, str(epgId), '', update_from_api=1) elif type == 'archiv_iptv': list_item = xbmcgui.ListItem(title) list_item = get_listitem_epg_details(list_item, str(epgId), '', update_from_api=1) else: list_item = xbmcgui.ListItem(path=url) if addon.getSetting('stream_type') == 'MPEG-DASH' or addon.getSetting( 'stream_type') == 'MPEG-DASH-web' or force_mpeg_dash == 1: list_item.setProperty('inputstreamaddon', 'inputstream.adaptive') list_item.setProperty('inputstream', 'inputstream.adaptive') list_item.setProperty('inputstream.adaptive.manifest_type', 'mpd') list_item.setMimeType('application/dash+xml') if type == 'archiv_iptv' or (type == 'live_iptv' and (addon.getSetting('stream_type') != 'HLS' or force_mpeg_dash == 1) and addon.getSetting('startover') == 'true') or type == 'live_iptv_epg': playlist = xbmc.PlayList(1) playlist.clear() if epgId is not None: event = get_epg_details([str(epgId)], update_from_api=1) list_item.setInfo('video', {'title': event['title']}) else: list_item.setInfo('video', {'title': channels_list[channelKey]['name']}) xbmc.PlayList(1).add(url, list_item) xbmc.Player().play(playlist) else: list_item.setContentLookup(False) xbmcplugin.setResolvedUrl(_handle, True, list_item)
def list_live(page, label): addon = xbmcaddon.Addon() xbmcplugin.setPluginCategory(_handle, label) channels = Channels() channels_list = channels.get_channels_list('number') num = 0 pagesize = int(addon.getSetting('live_pagesize')) channels_details = get_epg_live(len(channels_list.keys())) color = get_color(addon.getSetting('label_color_live')) startitem = (int(page) - 1) * pagesize i = 0 for num in sorted(channels_list.keys()): if i >= startitem and i < startitem + pagesize: channelName = channels_list[num]['name'] channelKey = channels_list[num]['channelKey'] if channelName in channels_details: title = channels_details[channelName]['title'] start = channels_details[channelName]['start'] end = channels_details[channelName]['end'] live = '[COLOR ' + str( color) + '] | ' + title + ' | ' + start.strftime( '%H:%M') + ' - ' + end.strftime('%H:%M') + '[/COLOR]' live_noncolor = ' | ' + title + ' | ' + start.strftime( '%H:%M') + ' - ' + end.strftime('%H:%M') list_item = xbmcgui.ListItem(label=encode(channelName) + encode(live)) list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': encode(channelName) + ' | ' + encode(title) }) list_item = get_listitem_epg_details( list_item, str(channels_details[channelName]['epgId']), channels_list[num]['logo']) else: live = '' live_noncolor = '' list_item = xbmcgui.ListItem(label=encode(channelName) + encode(live)) list_item.setInfo( 'video', { 'mediatype': 'movie', 'title': encode(channelName) + encode(live) }) list_item.setContentLookup(False) list_item.setProperty('IsPlayable', 'true') if channelName in channels_details: list_item.addContextMenuItems([ ('Související pořady', 'Container.Update(plugin://' + plugin_id + '?action=list_related&epgId=' + str(channels_details[channelName]['epgId']) + '&label=Související / ' + encode(channels_details[channelName]['title']) + ')'), ('Vysílání pořadu', 'Container.Update(plugin://' + plugin_id + '?action=list_same&epgId=' + str(channels_details[channelName]['epgId']) + '&label=' + encode(channels_details[channelName]['title']) + ')') ]) url = get_url(action='play_live', channelKey=encode(channelKey), title=encode(channelName) + encode(live_noncolor)) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) i = i + 1 if int(page) * pagesize <= i: list_item = xbmcgui.ListItem(label='další strana') url = get_url(action='list_live', page=int(page) + 1, label='další strana') list_item.setProperty('IsPlayable', 'false') xbmcplugin.addDirectoryItem(_handle, url, list_item, True) xbmcplugin.endOfDirectory(_handle, cacheToDisc=False)
def get_event(epgId, pvrProgramId, title): addon = xbmcaddon.Addon() err = 0 url = '' post = {} channelKey = '' stream_type = 'HLS' current_ts = int(time.mktime(datetime.now().timetuple())) event = get_epg_details([epgId], update_from_api=1) channels = Channels() channels_list = channels.get_channels_list('name', visible_filter=False) if event != None and (current_ts < event['availableTo'] or pvrProgramId is not None): if event['startTime'] < current_ts: if event['endTime'] < current_ts: if pvrProgramId == None: channelKey = channels_list[event['channel']]['channelKey'] session = Session() channels_list = channels.get_channels_list( visible_filter=False) header = get_header( session.get_service( channels_list[channelKey]['serviceid'])) subscription = session.get_service( channels_list[channelKey]['serviceid'])['subscription'] post = { 'serviceType': 'TIMESHIFT_TV', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'channelKey': encode(channelKey), 'fromTimestamp': str(event['startTime'] * 1000), 'toTimestamp': str(event['endTime'] * 1000 + (int(addon.getSetting('offset')) * 60 * 1000)), 'id': epgId, 'encryptionType': 'NONE' } else: session = Session() for serviceid in session.get_services(): data = call_o2_api( url='https://api.o2tv.cz/unity/api/v1/recordings/', data=None, header=get_header_unity( session.services[serviceid])) if 'err' in data: xbmcgui.Dialog().notification( 'Sledování O2TV', 'Problém s načtením nahrávek, zkuste to znovu', xbmcgui.NOTIFICATION_ERROR, 6000) if 'result' in data and len(data['result']) > 0: for program in data['result']: if program['pvrProgramId'] == pvrProgramId: channelKey = program['program'][ 'channelKey'] if len(channelKey) > 0: channels_list = channels.get_channels_list( visible_filter=False) header = get_header( session.get_service( channels_list[channelKey]['serviceid'])) subscription = session.get_service( channels_list[channelKey] ['serviceid'])['subscription'] post = { 'serviceType': 'NPVR', 'deviceType': addon.getSetting('devicetype'), 'streamingProtocol': stream_type, 'subscriptionCode': subscription, 'contentId': pvrProgramId, 'encryptionType': 'NONE' } else: xbmc.log('live') err = 1 else: xbmc.log('future') err = 1 else: xbmc.log('neni') err = 1 if err == 1: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s stažením ' + encode(title), xbmcgui.NOTIFICATION_ERROR, 5000) current_ts = int(time.mktime(datetime.now().timetuple())) db.execute( 'UPDATE queue SET status = -1, downloadts = ? WHERE epgId = ?', [str(current_ts), str(epgId)]) db.commit() return {}, '' else: if addon.getSetting('only_sd') == 'true': post.update({'resolution': 'SD'}) data = call_o2_api( url='https://app.o2tv.cz/sws/server/streaming/uris.json', data=post, header=header) if 'err' in data: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s stažením streamu', xbmcgui.NOTIFICATION_ERROR, 5000) url = '' if 'uris' in data and len( data['uris']) > 0 and 'uri' in data['uris'][0] and len( data['uris'][0]['uri']) > 0: for uris in data['uris']: if addon.getSetting( 'only_sd') != 'true' and uris['resolution'] == 'HD': url = uris['uri'] if addon.getSetting( 'only_sd') == 'true' and uris['resolution'] == 'SD': url = uris['uri'] if url == '': url = data['uris'][0]['uri'] else: xbmcgui.Dialog().notification('Sledování O2TV', 'Problém s stažením streamu', xbmcgui.NOTIFICATION_ERROR, 5000) return event, url