From e59ecfe9335aae4e1ed00779b29266ebcc2bedf7 Mon Sep 17 00:00:00 2001 From: Mariusz89B Date: Thu, 4 Aug 2022 23:25:34 +0200 Subject: [PATCH] v1.1.2 --- addon.py | 210 ++++++++++++++++-- addon.xml | 8 +- changelog.txt | 4 + resources/icons/live.png | Bin 0 -> 29755 bytes .../resource.language.da_dk/strings.po | 6 +- .../resource.language.en_gb/strings.po | 4 + .../resource.language.nb_no/strings.po | 6 +- .../resource.language.sv_se/strings.po | 6 +- 8 files changed, 223 insertions(+), 21 deletions(-) create mode 100644 resources/icons/live.png diff --git a/addon.py b/addon.py index 25dadb5..d5fa67a 100644 --- a/addon.py +++ b/addon.py @@ -95,6 +95,7 @@ fanart = os.path.join(resources, 'fanart.jpg') icon = os.path.join(path, 'icon.png') +live_icon = os.path.join(icons, 'live.png') tv_icon = os.path.join(icons, 'tv.png') vod_icon = os.path.join(icons, 'vod.png') sport_icon = os.path.join(icons, 'sport.png') @@ -520,6 +521,10 @@ def login_data(reconnect, retry=0): return False def video_on_demand(): + login = check_login() + if not login: + login_data(reconnect=False) + add_item(label=localized(30030), url='', mode='vod_genre_movies', icon=icon, fanart=fanart, folder=True, playable=False) add_item(label=localized(30031), url='', mode='vod_genre_series', icon=icon, fanart=fanart, folder=True, playable=False) @@ -869,6 +874,7 @@ def get_items(data, thumb=thumb, poster=poster, banner=banner, clearlogo=clearlo xbmcplugin.addSortMethod(addon_handle, sortMethod=xbmcplugin.SORT_METHOD_TITLE, label2Mask = "%R, %Y, %P") if title not in titles: + count += 1 add_item(label=title, url='vod', mode=mode, media_id=media_id, folder=folder, playable=playable, info_labels={'title': label, 'originaltitle': title, 'plot': plot, 'plotoutline': outline, 'aired': date, 'dateadded': date, 'duration': duration, 'genre': genre, 'userrating': rating, 'mpaa': age}, icon=icon, poster=poster, fanart=fanart, context_menu=context_menu, item_count=count) titles.add(title) @@ -992,16 +998,20 @@ def vod_episodes(season, season_id): episode_raw = item.get('episodeNumber') if episode_raw: episode_read = str(episode_raw['readable']) - nr_pattern = re.compile('(\d+)') + nr_pattern = re.compile(r'(\d+)') r = nr_pattern.search(episode_read) episode_nr = r.group(1) if r else '' + else: + episode_nr = '' season_raw = item.get('seasonNumber') if season_raw: season_read = str(season_raw['readable']) - nr_pattern = re.compile('(\d+)') + nr_pattern = re.compile(r'(\d+)') r = nr_pattern.search(season_read) season_nr = r.group(1) if r else '' + else: + season_nr = '' label = episode_read @@ -1171,6 +1181,10 @@ def vod_search(): return search def search(query): + login = check_login() + if not login: + login_data(reconnect=False) + if query: beartoken = addon.getSetting('teliaplay_beartoken') tv_client_boot_id = addon.getSetting('teliaplay_tv_client_boot_id') @@ -1211,6 +1225,146 @@ def search(query): data = j_response['data']['search2']['searchItems'] get_items(data) +def now_playing(thumb=thumb, poster=poster, banner=banner, clearlogo=clearlogo, icon=icon, fanart=fanart): + country = int(addon.getSetting('teliaplay_locale')) + beartoken = addon.getSetting('teliaplay_beartoken') + tv_client_boot_id = addon.getSetting('teliaplay_tv_client_boot_id') + + n = datetime.now() + now = int(time.mktime(n.timetuple())) * 1000 + + try: + url = 'https://graphql-telia.t6a.net/' + + headers = { + 'authorization': 'Bearer ' + beartoken, + 'tv-client-name': 'androidmob', + 'tv-client-version': '4.7.0', + 'tv-client-boot-id': tv_client_boot_id, + 'x-country': ca[country], + 'content-type': 'application/json', + 'accept-encoding': 'gzip', + 'user-agent': 'okhttp/4.9.3', + } + + json = { + "operationName": "GetEPGChannelList", + "query": "query GetEPGChannelList($channelLimit: Int, $programLimit: Int, $timestamp: Timestamp!) {\n channels(limit: $channelLimit) {\n channelItems {\n ...ChannelItem\n __typename\n }\n __typename\n }\n}\n\nfragment ChannelItem on Channel {\n id\n name\n recordAndWatch\n playback {\n play {\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n buy {\n ...GraphQLChannelPlaybackBuyFragment\n __typename\n }\n __typename\n }\n icons {\n light {\n sourceNonEncoded\n __typename\n }\n dark {\n sourceNonEncoded\n __typename\n }\n __typename\n }\n programs(timestamp: $timestamp, limit: $programLimit) {\n programItems {\n ...ProgramItem\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment PlaybackSpec on PlaybackSpec {\n accessControl\n videoId\n videoIdType\n watchMode\n __typename\n}\n\nfragment GraphQLChannelPlaybackBuyFragment on ChannelPlaybackBuy {\n subscriptions {\n item {\n ...GraphQLSubscriptionProductStandardFragment\n ...GraphQLSubscriptionProductIAPFragment\n ...GraphQLSubscriptionProductTVEFragment\n ...GraphQLSubscriptionProductDualEntry\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment GraphQLSubscriptionProductStandardFragment on SubscriptionProductStandard {\n id\n name\n uniqueSellingPoints {\n ...GraphQLSubscriptionProductUniqueSellingPoint\n __typename\n }\n gqlPrice: price {\n readable\n __typename\n }\n __typename\n}\n\nfragment GraphQLSubscriptionProductUniqueSellingPoint on SubscriptionProductUniqueSellingPoint {\n sellingPoint\n __typename\n}\n\nfragment GraphQLSubscriptionProductIAPFragment on SubscriptionProductIAP {\n id\n name\n iTunesConnectId\n uniqueSellingPoints {\n ...GraphQLSubscriptionProductUniqueSellingPoint\n __typename\n }\n __typename\n}\n\nfragment GraphQLSubscriptionProductTVEFragment on SubscriptionProductTVE {\n id\n name\n __typename\n}\n\nfragment GraphQLSubscriptionProductDualEntry on SubscriptionProductDualEntry {\n id\n name\n __typename\n}\n\nfragment ProgramItem on Program {\n live\n id\n startTime {\n timestamp\n isoString\n __typename\n }\n endTime {\n timestamp\n isoString\n __typename\n }\n title\n media {\n ... on Movie {\n ...MovieProgram\n __typename\n }\n ... on Episode {\n ...EpisodeProgram\n __typename\n }\n ... on SportEvent {\n ...SportProgram\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment MovieProgram on Movie {\n id\n images {\n screenshot16x9 {\n sourceNonEncoded\n __typename\n }\n backdrop16x9 {\n sourceNonEncoded\n __typename\n }\n __typename\n }\n mediaType\n title\n availableNow\n availability {\n from {\n timestamp\n __typename\n }\n to {\n timestamp\n text\n __typename\n }\n __typename\n }\n descriptionLong\n playback {\n ...PlaybackItem\n buy {\n ...GraphQLPlaybackBuyFragment\n ...BuyItem\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment PlaybackItem on Playback {\n play {\n linear {\n ...Linear\n __typename\n }\n subscription {\n item {\n validFrom {\n timestamp\n __typename\n }\n validTo {\n timestamp\n __typename\n }\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n __typename\n }\n npvr {\n item {\n validFrom {\n timestamp\n __typename\n }\n validTo {\n timestamp\n __typename\n }\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n live {\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n startover {\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n npvrInfo {\n originalAirDate {\n startDate {\n timestamp\n isoString\n __typename\n }\n __typename\n }\n series {\n active\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment Linear on PlaybackPlayLinear {\n item {\n isLive\n startover {\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n startTime {\n timestamp\n readableDistance(type: FUZZY)\n __typename\n }\n endTime {\n timestamp\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment GraphQLPlaybackBuyFragment on PlaybackBuy {\n subscriptions {\n item {\n ...GraphQLSubscriptionProductStandardFragment\n ...GraphQLSubscriptionProductIAPFragment\n ...GraphQLSubscriptionProductTVEFragment\n ...GraphQLSubscriptionProductDualEntry\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment BuyItem on PlaybackBuy {\n subscription {\n item {\n validFrom {\n timestamp\n __typename\n }\n validTo {\n timestamp\n __typename\n }\n __typename\n }\n __typename\n }\n npvr {\n item {\n validFrom {\n timestamp\n __typename\n }\n validTo {\n timestamp\n __typename\n }\n playbackSpec {\n ...PlaybackSpec\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment EpisodeProgram on Episode {\n id\n images {\n screenshot16x9 {\n sourceNonEncoded\n __typename\n }\n backdrop16x9 {\n sourceNonEncoded\n __typename\n }\n __typename\n }\n availableNow\n availability {\n from {\n timestamp\n __typename\n }\n to {\n timestamp\n text\n __typename\n }\n __typename\n }\n title\n descriptionLong\n series {\n id\n title\n isRecordable\n userData {\n npvrInfo {\n active\n episodes {\n ongoing\n recorded\n scheduled\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n playback {\n ...PlaybackItem\n buy {\n ...GraphQLPlaybackBuyFragment\n ...BuyItem\n __typename\n }\n __typename\n }\n episodeNumber {\n readable\n __typename\n }\n seasonNumber {\n readable\n __typename\n }\n __typename\n}\n\nfragment SportProgram on SportEvent {\n id\n title\n availableNow\n availability {\n from {\n timestamp\n __typename\n }\n to {\n timestamp\n text\n __typename\n }\n __typename\n }\n playback {\n ...PlaybackItem\n buy {\n ...GraphQLPlaybackBuyFragment\n ...BuyItem\n __typename\n }\n __typename\n }\n __typename\n}\n", + "variables": { + "channelLimit": 200, + "programLimit": 1, + "timestamp": int(now), + } + } + + response = send_req(url, post=True, json=json, headers=headers) + if not response: + xbmcgui.Dialog().notification(localized(30012), localized(30006)) + raise Exception + + j_response = response.json() + channels = j_response['data']['channels']['channelItems'] + + count = 0 + + for channel in channels: + ch_name = channel.get('name') + programs = channel.get('programs') + icons = channel.get('icons') + exlink = channel.get('id') + + if icons: + dark = icons.get('dark') + if dark: + src = dark.get('sourceNonEncoded') + if src: + icon = unquote(src) + + if programs: + program_items = programs.get('programItems') + for program in program_items: + start = program.get('startTime') + if start: + start_ts = start.get('timestamp') + if isinstance(start_ts, int): + start_time = start_ts // 1000 + dt_start = datetime.fromtimestamp(start_time) + st_start = dt_start.strftime('%H:%M') + else: + st_start = None + + end = program.get('endTime') + if end: + end_ts = end.get('timestamp') + if isinstance(end_ts, int): + end_time = end_ts // 1000 + dt_end = datetime.fromtimestamp(end_time) + st_end = dt_end.strftime('%H:%M') + else: + st_end = None + + title = program.get('title') + + media = program.get('media') + if media: + count += 1 + media_id = media.get('id') + + images = media.get('images') + if images: + card_16x9 = images.get('screenshot16x9') if images.get('screenshot16x9') else images.get('backdrop16x9') + if card_16x9: + src = card_16x9.get('sourceNonEncoded') + if not src: + src = card_16x9.get('source') + if src: + poster = unquote(src) + + plot = media.get('descriptionLong') + outline = plot + + today = datetime.strftime(datetime.now(), '%Y-%m-%d') + + if st_start and st_end: + date = st_start + ' - ' + st_end + duration = int(end_time) - int(start_time) + else: + date = '' + duration = '' + + label = title + '[B][COLOR violet] ● [/COLOR][/B]' + '[COLOR grey]({0})[/COLOR]'.format(date) + + episode_raw = media.get('episodeNumber') + if episode_raw: + episode_read = str(episode_raw['readable']) + nr_pattern = re.compile(r'(\d+)') + r = nr_pattern.search(episode_read) + episode_nr = r.group(1) if r else '' + else: + episode_nr = '' + + season_raw = media.get('seasonNumber') + if season_raw: + season_read = str(season_raw['readable']) + nr_pattern = re.compile(r'(\d+)') + r = nr_pattern.search(season_read) + season_nr = r.group(1) if r else '' + else: + season_nr = '' + + catchup = 'LIVE' + + ext = localized(30027) + context_menu = [('{0}'.format(ext), 'RunScript(plugin.video.teliaplay,0,?mode=ext,label={0})'.format(title))] + + add_item(label=label, url=exlink, mode='play', media_id=media_id, catchup=catchup, start=start_time, end=end_time, folder=False, playable=True, info_labels={'title': label, 'originaltitle': title, 'plot': plot, 'plotoutline': outline, 'aired': today, 'dateadded': today, 'duration': duration, 'sortepisode': episode_nr, 'sortseason': season_nr}, icon=icon, poster=poster, fanart=fanart, context_menu=context_menu, item_count=count) + + xbmcplugin.setContent(addon_handle, 'playlists') + xbmcplugin.endOfDirectory(addon_handle) + + except Exception as ex: + print('live_channels exception: {}'.format(ex)) + def live_channels(): channel_lst = [] @@ -1386,16 +1540,28 @@ def live_channel(exlink, extitle): now = int(time.time()) try: - start = program['startTime']['timestamp'] // 1000 - dt_start = datetime.fromtimestamp(start) - st_start = dt_start.strftime('%H:%M') - da_start = dt_start.strftime('%Y-%m-%d') - - end = program['endTime']['timestamp'] // 1000 - dt_end = datetime.fromtimestamp(end) - st_end = dt_end.strftime('%H:%M') + start = program.get('startTime') + if start: + start_ts = start.get('timestamp') + if isinstance(start_ts, int): + start_time = start_ts // 1000 + dt_start = datetime.fromtimestamp(start_time) + st_start = dt_start.strftime('%H:%M') + da_start = dt_start.strftime('%Y-%m-%d') + else: + st_start = None + + end = program.get('endTime') + if end: + end_ts = end.get('timestamp') + if isinstance(end_ts, int): + end_time = end_ts // 1000 + dt_end = datetime.fromtimestamp(end_time) + st_end = dt_end.strftime('%H:%M') + else: + st_end = None - duration = end - start + duration = int(end_time) - int(start_time) aired = da_start date = st_start + ' - ' + st_end @@ -1403,10 +1569,10 @@ def live_channel(exlink, extitle): if len(title) > 50: title = title[:50] - if int(now) >= int(start) and int(now) <= int(end): + if int(now) >= int(start_time) and int(now) <= int(end_time): name_ = title + '[B][COLOR violet] ● [/COLOR][/B]' - elif int(end) >= int(now): + elif int(end_time) >= int(now): name_ = '[COLOR grey]{0}[/COLOR] [B][/B]'.format(title) else: @@ -1418,8 +1584,8 @@ def live_channel(exlink, extitle): name_ = title + '[B][COLOR violet] ● [/COLOR][/B]' name = name_ + '[COLOR grey](00:00 - 23:59)[/COLOR]' - start = 0 - end = 0 + start_time = 0 + end_time = 0 duration = '' @@ -1477,7 +1643,7 @@ def live_channel(exlink, extitle): ext = localized(30027) context_menu = [('{0}'.format(ext), 'RunScript(plugin.video.teliaplay,0,?mode=ext,label={0})'.format(title))] - add_item(label=name, url=exlink, mode='play', media_id=media_id, catchup=catchup, start=start, end=end, folder=False, playable=True, info_labels={'title': title, 'originaltitle': org_title, 'plot': plot, 'plotoutline': plot, 'aired': aired, 'dateadded': date, 'duration': duration, 'genre': genre, 'country': lang}, icon=icon, poster=poster, fanart=fanart, context_menu=context_menu, item_count=count) + add_item(label=name, url=exlink, mode='play', media_id=media_id, catchup=catchup, start=start_time, end=end_time, folder=False, playable=True, info_labels={'title': title, 'originaltitle': org_title, 'plot': plot, 'plotoutline': plot, 'aired': aired, 'dateadded': date, 'duration': duration, 'genre': genre, 'country': lang}, icon=icon, poster=poster, fanart=fanart, context_menu=context_menu, item_count=count) xbmcplugin.setContent(addon_handle, 'sets') xbmcplugin.endOfDirectory(addon_handle) @@ -1628,6 +1794,10 @@ def get_stream(exlink, catchup_type): return None, None def sports_page(): + login = check_login() + if not login: + login_data(reconnect=False) + add_item(label=localized(30049), url='', mode='sports_table_genre', icon=icon, fanart=fanart, folder=True, playable=False) add_item(label=localized(30050), url='', mode='sports_corner_genre', icon=icon, fanart=fanart, folder=True, playable=False) @@ -1915,6 +2085,10 @@ def sports_corner(genre_id): return def kids_genre(): + login = check_login() + if not login: + login_data(reconnect=False) + beartoken = addon.getSetting('teliaplay_beartoken') tv_client_boot_id = addon.getSetting('teliaplay_tv_client_boot_id') @@ -2128,6 +2302,7 @@ def home(): if login and not childmode: add_item(label=localized(30009).format(profile_name), url='', mode='logged', icon=profile_avatar, fanart=fanart, folder=False, playable=False) + add_item(label=localized(30067), url='', mode='now_playing', icon=live_icon, fanart=fanart, folder=True, playable=False) add_item(label=localized(30010), url='', mode='channels', icon=tv_icon, fanart=fanart, folder=True, playable=False) add_item(label=localized(30011), url='', mode='video_on_demand', icon=vod_icon, fanart=fanart, folder=True, playable=False) add_item(label=localized(30039), url='', mode='sports_page', icon=sport_icon, fanart=fanart, folder=True, playable=False) @@ -2273,6 +2448,9 @@ def router(param): elif mode == 'programs': live_channel(exlink, extitle) + elif mode == 'now_playing': + now_playing() + elif mode == 'channels': live_channels() diff --git a/addon.xml b/addon.xml index f520b0e..ac16dac 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -24,7 +24,11 @@ all GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 and MIT LICENSE. https://github.com/Mariusz89B/plugin.video.teliaplay - v1.1.1 (2022-07-30) + v1.1.2 (2022-08-04) +- Added Live TV. +- Other fixes. + +v1.1.1 (2022-07-30) - Fixed series categories. - Performance optimizations. - Other fixes. diff --git a/changelog.txt b/changelog.txt index 87915d8..7e2bd8c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +v1.1.2 (2022-08-04) +- Added Live TV. +- Other fixes. + v1.1.1 (2022-07-30) - Fixed series categories. - Performance optimizations. diff --git a/resources/icons/live.png b/resources/icons/live.png new file mode 100644 index 0000000000000000000000000000000000000000..2a44fc57684873790ee5764fd21c871200ee5b64 GIT binary patch literal 29755 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