From aefa7d3d72e3a461ec6db79fe305023395118cf1 Mon Sep 17 00:00:00 2001 From: Sylvain CECCHETTO Date: Wed, 22 Mar 2017 03:24:43 +0100 Subject: [plugin.video.catchuptvandmore] 0.1.0 (#989) --- .../resources/lib/channels/fr/6play.py | 381 +++++++++++++++++++++ .../resources/lib/channels/fr/__init__.py | 0 .../resources/lib/channels/fr/arte.py | 260 ++++++++++++++ .../resources/lib/channels/fr/bfmtv.py | 224 ++++++++++++ .../resources/lib/channels/fr/c.py | 210 ++++++++++++ .../resources/lib/channels/fr/canalplus.py | 318 +++++++++++++++++ .../resources/lib/channels/fr/gulli.py | 203 +++++++++++ .../resources/lib/channels/fr/itele.py | 192 +++++++++++ .../resources/lib/channels/fr/pluzz.py | 282 +++++++++++++++ .../resources/lib/channels/fr/tf1.py | 238 +++++++++++++ 10 files changed, 2308 insertions(+) create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/__init__.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/canalplus.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py create mode 100755 plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py (limited to 'plugin.video.catchuptvandmore/resources/lib/channels/fr') diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py new file mode 100755 index 0000000..d60ebd0 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py @@ -0,0 +1,381 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Original work (C) JUL1EN094, SPM, SylvainCecchetto + Copyright (C) 2016 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + + +import json +from resources.lib import utils +from resources.lib import common + + +# Url to get channel's categories +# e.g. Info, Divertissement, Séries, ... +# We get an id by category +url_root = 'http://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/%sreplay/folders?limit=999&offset=0' + +# Url to get catgory's programs +# e.g. Le meilleur patissier, La france à un incroyable talent, ... +# We get an id by program +url_category = 'http://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/6play/folders/%s/programs' \ + '?limit=999&offset=0&csa=9&with=parentcontext' + +# Url to get program's subfolders +# e.g. Saison 5, Les meilleurs moments, les recettes pas à pas, ... +# We get an id by subfolder +url_subcategory = 'http://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/6play/programs/%s' \ + '?with=links,subcats,rights' + + +# Url to get shows list +# e.g. Episode 1, Episode 2, ... +url_videos = 'http://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/6play/programs/%s/videos?' \ + 'csa=6&with=clips,freemiumpacks&type=vi,vc,playlist&limit=999'\ + '&offset=0&subcat=%s&sort=subcat' + +url_videos2 = 'https://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/6play/programs/%s/videos?' \ + 'csa=6&with=clips,freemiumpacks&type=vi&limit=999&offset=0' + + +url_json_video = 'https://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/6play/videos/%s'\ + '?csa=9&with=clips,freemiumpacks' + + +url_img = 'https://images.6play.fr/v1/images/%s/raw' + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + shows = [] + + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + url_root % (params.channel_name), + '%s.json' % (params.channel_name), + random_ua=True) + file_prgm = open(file_path).read() + json_parser = json.loads(file_prgm) + + # do not cache failed catalog fetch + # the error format is: + # {"error":{"code":403,"message":"Forbidden"}} + if isinstance(json_parser, dict) and \ + 'error' in json_parser.keys(): + utils.os.remove(file_path) + raise Exception('Failed to fetch the 6play catalog') + + for array in json_parser: + category_id = str(array['id']) + category_name = array['name'].encode('utf-8') + shows.append({ + 'label': category_name, + 'url': common.plugin.get_url( + action='channel_entry', + category_id=category_id, + next='list_shows_2', + title=category_name + ) + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_2': + file_prgm = utils.get_webcontent( + url_category % (params.category_id), + random_ua=True) + json_parser = json.loads(file_prgm) + + for array in json_parser: + program_title = array['title'].encode('utf-8') + program_id = str(array['id']) + program_desc = array['description'].encode('utf-8') + program_imgs = array['images'] + program_img = '' + for img in program_imgs: + if img['role'].encode('utf-8') == 'vignette': + external_key = img['external_key'].encode('utf-8') + program_img = url_img % (external_key) + elif img['role'].encode('utf-8') == 'carousel': + external_key = img['external_key'].encode('utf-8') + program_fanart = url_img % (external_key) + + info = { + 'video': { + 'title': program_title, + 'plot': program_desc + } + } + shows.append({ + 'label': program_title, + 'thumb': program_img, + 'fanart': program_fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_shows_3', + program_id=program_id, + program_img=program_img, + program_fanart=program_fanart, + program_desc=program_desc, + title=program_title + ), + 'info': info + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_3': + program_json = utils.get_webcontent( + url_subcategory % (params.program_id), + random_ua=True) + + json_parser = json.loads(program_json) + for sub_category in json_parser['program_subcats']: + sub_category_id = str(sub_category['id']) + sub_category_title = sub_category['title'].encode('utf-8') + + info = { + 'video': { + 'title': sub_category_title, + 'plot': params.program_desc + } + } + + shows.append({ + 'label': sub_category_title, + 'thumb': params.program_img, + 'fanart': params.program_fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos', + program_id=params.program_id, + sub_category_id=sub_category_id + ), + 'info': info + }) + + info = { + 'video': { + 'title': common.addon.get_localized_string(30101), + 'plot': params.program_desc + } + } + shows.append({ + 'label': common.addon.get_localized_string(30101), + 'thumb': params.program_img, + 'fanart': params.program_fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos', + program_id=params.program_id, + sub_category_id='null' + + ), + 'info': info + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + return shows + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + + if params.sub_category_id == 'null': + url = url_videos2 % params.program_id + else: + url = url_videos % (params.program_id, params.sub_category_id) + program_json = utils.get_webcontent( + url, + random_ua=True) + json_parser = json.loads(program_json) + + for video in json_parser: + video_id = str(video['id']) + + title = video['title'].encode('utf-8') + duration = video['clips'][0]['duration'] + description = video['description'].encode('utf-8') + try: + aired = video['clips'][0]['product']['last_diffusion'] + aired = aired.encode('utf-8') + aired = aired[:10] + year = aired[:4] + # date : string (%d.%m.%Y / 01.01.2009) + # aired : string (2008-12-07) + day = aired.split('-')[2] + mounth = aired.split('-')[1] + year = aired.split('-')[0] + date = '.'.join((day, mounth, year)) + + except: + aired = '' + year = '' + date = '' + img = '' + + program_imgs = video['clips'][0]['images'] + program_img = '' + for img in program_imgs: + if img['role'].encode('utf-8') == 'vignette': + external_key = img['external_key'].encode('utf-8') + program_img = url_img % (external_key) + + info = { + 'video': { + 'title': title, + 'plot': description, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': program_img, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + video_id=video_id, + ), + 'is_playable': True, + 'info': info + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ), + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + video_json = utils.get_webcontent( + url_json_video % (params.video_id), + random_ua=True) + json_parser = json.loads(video_json) + + video_assets = json_parser['clips'][0]['assets'] + url = '' + url2 = '' + url3 = '' + for asset in video_assets: + if 'ism' in asset['video_container'].encode('utf-8'): + url = asset['full_physical_path'].encode('utf-8') + if 'mp4' in asset['video_container'].encode('utf-8'): + if 'hd' in asset['video_quality'].encode('utf-8'): + url2 = asset['full_physical_path'].encode('utf-8') + else: + url3 = asset['full_physical_path'].encode('utf-8') + manifest_url = '' + if url: + manifest_url = url + elif url2: + manifest_url = url2 + else: + manifest_url = url3 + + manifest = utils.get_webcontent( + manifest_url, + random_ua=True) + if 'drm' in manifest: + utils.send_notification(common.addon.get_localized_string(30102)) + return '' + + desired_quality = common.plugin.get_setting( + params.channel_id + '.quality') + + if desired_quality == 'Auto': + return manifest_url + + root = common.os.path.dirname(manifest_url) + + url_sd = '' + url_hd = '' + url_ultra_sd = '' + url_ultra_hd = '' + + lines = manifest.splitlines() + for k in range(0, len(lines) - 1): + if 'RESOLUTION=400' in lines[k]: + url_ultra_sd = root + '/' + lines[k + 1] + elif 'RESOLUTION=640' in lines[k]: + url_sd = root + '/' + lines[k + 1] + elif 'RESOLUTION=720' in lines[k]: + url_hd = root + '/' + lines[k + 1] + elif 'RESOLUTION=1080' in lines[k]: + url_ultra_hd = root + '/' + lines[k + 1] + + if desired_quality == 'Force HD': + if url_ultra_hd: + return url_ultra_hd + elif url_hd: + return url_hd + return manifest_url + + elif desired_quality == 'Force SD': + if url_ultra_sd: + return url_ultra_sd + elif url_sd: + return url_sd + return manifest_url diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/__init__.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py new file mode 100755 index 0000000..f2b7a2b --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Copyright (C) 2016 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + +authorization_key = 'Bearer OTE3NjJhOTYwNzQzNWY0MGE0OGI5MGQ0YmVm' \ + 'MWY2Y2JiYzc5NDQzY2IxMmYxYjQ0NDVlYmEyOTBmYjVkMDg3OQ' + +headers = {'Authorization': authorization_key} + +url_categories = 'https://api-cdn.arte.tv/api/opa/v2/categories?' \ + 'language=%s&limit=100&sort=order' +# Valid languages list : fr|de|en|es|pl + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + shows = [] + + disered_language = common.plugin.get_setting( + params.channel_id + '.language') + + if disered_language == 'Auto': + disered_language = params.channel_country + + file_path = utils.download_catalog( + url_categories % disered_language, + '%s.json' % params.channel_name, + specific_headers=headers) + file_categories = open(file_path).read() + json_parser = json.loads(file_categories) + + for category in json_parser['categories']: + label = category['label'].encode('utf-8') + desc = category['description'].encode('utf-8') + href = category['links']['videos']['href'].encode('utf-8') + code = category['code'].encode('utf-8') + + info = { + 'video': { + 'title': label, + 'plot': desc + } + } + + shows.append({ + 'label': label, + 'url': common.plugin.get_url( + action='channel_entry', + code=code, + href=href, + next='list_videos', + title=label + ), + 'info': info + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + + params_url = { + 'geoblockingZone': 'EUR_DE_FR,ALL,SAT,DE_FR', + 'imageSize': '1920x1080,625x224,940x530,720x406,400x225', + 'kind': 'SHOW', + 'limit': '100', + 'platform': 'ARTEPLUS7', + 'sort': '-broadcastBegin', + 'videoLibrary': 'true' + } + file_path = utils.download_catalog( + params.href, + '%s.json' % (params.channel_name + params.code), + specific_headers=headers, + params=params_url) + file_shows = open(file_path).read() + json_parser = json.loads(file_shows) + + for video in json_parser['videos']: + title = video['title'].encode('utf-8') + subtitle = '' + if video['subtitle'] is not None: + subtitle = video['subtitle'].encode('utf-8') + + original_title = video['originalTitle'].encode('utf-8') + plotoutline = '' + if video['shortDescription'] is not None: + plotoutline = video['shortDescription'].encode('utf-8') + plot = '' + if video['fullDescription'] is not None: + plot = video['fullDescription'].encode('utf-8') + duration = video['durationSeconds'] + year_prod = video['productionYear'] + genre = video['genrePresse'].encode('utf-8') + season = video['season'] + episode = video['episode'] + total_episodes = video['totalEpisodes'] + href = video['links']['videoStreams']['href'].encode('utf-8') + views = video['views'] + director = video['director'] + aired = video['arteSchedulingDay'] # year-mounth-day + day = aired.split('-')[2] + mounth = aired.split('-')[1] + year = aired.split('-')[0] + date = '.'.join((day, mounth, year)) + fanart = video['mainImage']['url'].encode('utf-8') + thumb = video['mainImage']['alternateResolutions'][1]['url'].encode('utf-8') + + if subtitle: + title = title + ' - [I]' + subtitle + '[/I]' + + info = { + 'video': { + 'title': title, + 'originaltitle': original_title, + 'plot': plot, + 'plotoutline': plotoutline, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year_prod, + 'genre': genre, + 'season': season, + 'episode': episode, + 'playcount': views, + 'director': director, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'fanart': fanart, + 'thumb': thumb, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + href=href, + ), + 'is_playable': True, + 'info': info + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_GENRE, + common.sp.xbmcplugin.SORT_METHOD_PLAYCOUNT, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ), + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + file_medias = utils.get_webcontent( + params.href, + specific_headers=headers) + json_parser = json.loads(file_medias) + + url_auto = '' + url_hd_plus = '' + url_hd = '' + url_sd = '' + url_sd_minus = '' + for video_stream in json_parser['videoStreams']: + if video_stream['audioSlot'] == 1: + if video_stream['quality'] == 'AQ' or \ + video_stream['quality'] == 'XQ': + url_auto = video_stream['url'].encode('utf-8') + + elif video_stream['quality'] == 'SQ' and \ + video_stream['mediaType'] == 'mp4' and \ + video_stream['protocol'] == 'HTTP': + url_hd_plus = video_stream['url'].encode('utf-8') + + elif video_stream['quality'] == 'EQ' and \ + video_stream['mediaType'] == 'mp4' and \ + video_stream['protocol'] == 'HTTP': + url_hd = video_stream['url'].encode('utf-8') + + elif video_stream['quality'] == 'HQ' and \ + video_stream['mediaType'] == 'mp4' and \ + video_stream['protocol'] == 'HTTP': + url_sd = video_stream['url'].encode('utf-8') + + elif video_stream['quality'] == 'MQ' and \ + video_stream['mediaType'] == 'mp4' and \ + video_stream['protocol'] == 'HTTP': + url_sd_minus = video_stream['url'].encode('utf-8') + + desired_quality = common.plugin.get_setting( + params.channel_id + '.quality') + + if desired_quality == 'Auto' and url_auto: + return url_auto + + if desired_quality == 'HD+' and url_hd_plus: + return url_hd_plus + elif url_hd: + return url_hd + + if desired_quality == 'HD' and url_hd: + return url_hd + elif url_hd_plus: + return url_hd_plus + + if desired_quality == 'SD' and url_sd: + return url_sd + elif url_sd_minus: + return url_sd_minus + + if desired_quality == 'SD-' and url_sd_minus: + return url_sd_minus + elif url_sd: + return url_sd + + return url_auto diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py new file mode 100755 index 0000000..f88615b --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +''' + Catch-up TV & More + Copyright (C) 2017 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +''' + +import json +from resources.lib import utils +from resources.lib import common + +url_token = 'http://api.nextradiotv.com/bfmtv-applications/' + +url_menu = 'http://www.bfmtv.com/static/static-mobile/bfmtv/' \ + 'ios-smartphone/v0/configuration.json' + +url_replay = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ + 'getPage?pagename=replay' +# token + +url_show = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ + 'getVideosList?category=%s&count=100&page=%s' +# token, category, page_number + +url_video = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ + 'getVideo?idVideo=%s' +# token, video_id + + +@common.plugin.cached(common.cache_time) +def get_token(): + file_token = utils.get_webcontent(url_token) + token_json = json.loads(file_token) + return token_json['session']['token'].encode('utf-8') + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + # Create categories list + shows = [] + + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + url_replay % get_token(), + '%s.json' % (params.channel_name)) + file_categories = open(file_path).read() + json_categories = json.loads(file_categories) + json_categories = json_categories['page']['contents'][0] + json_categories = json_categories['elements'][0]['items'] + + for categories in json_categories: + title = categories['title'].encode('utf-8') + image_url = categories['image_url'].encode('utf-8') + category = categories['categories'].encode('utf-8') + + shows.append({ + 'label': title, + 'thumb': image_url, + 'url': common.plugin.get_url( + action='channel_entry', + category=category, + next='list_videos_1', + title=title, + page='1' + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + if params.next == 'list_videos_1': + file_path = utils.download_catalog( + url_show % ( + get_token(), + params.category, + params.page), + '%s_%s_%s.json' % ( + params.channel_name, + params.category, + params.page)) + file_show = open(file_path).read() + json_show = json.loads(file_show) + + for video in json_show['videos']: + video_id = video['video'].encode('utf-8') + video_id_ext = video['id_ext'].encode('utf-8') + category = video['category'].encode('utf-8') + title = video['title'].encode('utf-8') + description = video['description'].encode('utf-8') + begin_date = video['begin_date'] # 1486725600, + image = video['image'].encode('utf-8') + duration = video['video_duration_ms'] / 1000 + + info = { + 'video': { + 'title': title, + 'plot': description, + #'aired': aired, + #'date': date, + 'duration': duration, + #'year': year, + 'genre': category, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': image, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + video_id=video_id, + video_id_ext=video_id_ext + ), + 'is_playable': True, + 'info': info + }) + + # More videos... + videos.append({ + 'label': common.addon.get_localized_string(30100), + 'url': common.plugin.get_url( + action='channel_entry', + category=params.category, + next='list_videos_1', + title=title, + page=str(int(params.page) + 1) + ) + + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_GENRE, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ), + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + file_medias = utils.get_webcontent( + url_video % (get_token(), params.video_id)) + json_parser = json.loads(file_medias) + + url_hd_plus = '' + url_hd = '' + url_sd = '' + url_sd_minus = '' + url_default = '' + + for media in json_parser['video']['medias']: + if media['frame_height'] == 270: + url_sd_minus = media['video_url'].encode('utf-8') + elif media['frame_height'] == 360: + url_sd = media['video_url'].encode('utf-8') + elif media['frame_height'] == 720: + url_hd = media['video_url'].encode('utf-8') + elif media['frame_height'] == 1080: + url_hd_plus = media['video_url'].encode('utf-8') + url_default = media['video_url'].encode('utf-8') + + desired_quality = common.plugin.get_setting( + params.channel_id + '.quality') + + if desired_quality == 'HD+' and url_hd_plus: + return url_hd_plus + elif url_hd: + return url_hd + + if desired_quality == 'HD' and url_hd: + return url_hd + elif url_hd_plus: + return url_hd_plus + + if desired_quality == 'SD' and url_sd: + return url_sd + elif url_sd_minus: + return url_sd_minus + + if desired_quality == 'SD-' and url_sd_minus: + return url_sd_minus + elif url_sd: + return url_sd + + return url_default diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py new file mode 100755 index 0000000..84d3b2d --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Copyright (C) 2017 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + + +url_root = 'http://lab.canal-plus.pro/web/app_prod.php/api/replay/%s' +# Channel id : +# c8 : 1 +# cstar : 2 + +url_shows = 'http://lab.canal-plus.pro/web/app_prod.php/api/pfv/list/%s/%s' +# channel_id/show_id + +url_video = 'http://lab.canal-plus.pro/web/app_prod.php/api/pfv/video/%s/%s' +# channel_id/video_id + + +def get_channel_id(params): + if params.channel_name == 'c8': + return '1' + elif params.channel_name == 'cstar': + return '2' + else: + return '1' + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + # Create categories list + shows = [] + + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + url_root % get_channel_id(params), + '%s.json' % (params.channel_name)) + file_categories = open(file_path).read() + json_categories = json.loads(file_categories) + + for categories in json_categories: + title = categories['title'].encode('utf-8') + slug = categories['slug'].encode('utf-8') + + shows.append({ + 'label': title, + 'url': common.plugin.get_url( + action='channel_entry', + slug=slug, + next='list_shows_2', + title=title + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_2': + # Create category's programs list + file_path = utils.download_catalog( + url_root % get_channel_id(params), + '%s_%s.json' % (params.channel_name, params.slug)) + file_categories = open(file_path).read() + json_categories = json.loads(file_categories) + + for categories in json_categories: + if categories['slug'].encode('utf-8') == params.slug: + for programs in categories['programs']: + id = str(programs['id']) + title = programs['title'].encode('utf-8') + slug = programs['slug'].encode('utf-8') + videos_recent = str(programs['videos_recent']) + + shows.append({ + 'label': title, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos', + id=id, + videos_recent=videos_recent, + slug=slug, + title=title + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + file_path = utils.download_catalog( + url_shows % (get_channel_id(params), params.videos_recent), + '%s_%s.json' % (params.channel_name, params.videos_recent)) + file_videos = open(file_path).read() + videos_json = json.loads(file_videos) + + for video in videos_json: + id = video['ID'].encode('utf-8') + try: + duration = int(video['DURATION'].encode('utf-8')) + except: + duration = 0 + description = video['INFOS']['DESCRIPTION'].encode('utf-8') + views = int(video['INFOS']['NB_VUES'].encode('utf-8')) + try: + date_video = video['INFOS']['DIFFUSION']['DATE'].encode('utf-8') # 31/12/2017 + except: + date_video = "00/00/0000" + day = date_video.split('/')[0] + mounth = date_video.split('/')[1] + year = date_video.split('/')[2] + aired = '-'.join((day, mounth, year)) + date = date_video.replace('/', '.') + title = video['INFOS']['TITRAGE']['TITRE'].encode('utf-8') + subtitle = video['INFOS']['TITRAGE']['SOUS_TITRE'].encode('utf-8') + thumb = video['MEDIA']['IMAGES']['GRAND'].encode('utf-8') + category = video['RUBRIQUAGE']['CATEGORIE'].encode('utf-8') + + if subtitle: + title = title + ' - [I]' + subtitle + '[/I]' + + info = { + 'video': { + 'title': title, + 'plot': description, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'genre': category, + 'playcount': views, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': thumb, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + id=id, + ), + 'is_playable': True, + 'info': info + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_GENRE, + common.sp.xbmcplugin.SORT_METHOD_PLAYCOUNT, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ), + content='tvshows') + + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + file_video = utils.get_webcontent( + url_video % (get_channel_id(params), params.id) + ) + video_json = json.loads(file_video) + return video_json['main']['MEDIA']['VIDEOS']['HLS'].encode('utf-8') + diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/canalplus.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/canalplus.py new file mode 100755 index 0000000..12240ef --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/canalplus.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Original work (C) JUL1EN094, SPM, SylvainCecchetto + Copyright (C) 2016 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + + +url_auth = 'http://service.mycanal.fr/authenticate.json/iphone/' \ + '1.6?highResolution=1&isActivated=0&isAuthenticated=0&paired=0' + +url_categories = 'http://service.mycanal.fr/page/%s/4578.json?' \ + 'cache=60000&nbContent=96' + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +def get_token(): + token_json = utils.get_webcontent(url_auth) + token_json = json.loads(token_json) + token = token_json['token'] + return token + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + # Create categories list + shows = [] + + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + url_categories % get_token(), + '%s.json' % (params.channel_name)) + file_categories = open(file_path).read() + json_categories = json.loads(file_categories) + + for strate in json_categories['strates']: + if strate['type'] == 'textList': + for content in strate['contents']: + title = content['title'].encode('utf-8') + url_page = content['onClick']['URLPage'].encode('utf-8') + + shows.append({ + 'label': title, + 'url': common.plugin.get_url( + action='channel_entry', + url_page=url_page, + next='list_shows_2', + title=title + ) + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_2': + # Create category's programs list + file_path = utils.download_catalog( + params.url_page, + '%s.json' % (params.title)) + file_shows = open(file_path).read() + shows_json = json.loads(file_shows) + + for strate in shows_json['strates']: + if strate['type'] == 'contentGrid': + for content in strate['contents']: + title = content['title'].encode('utf-8') + try: + subtitle = content['subtitle'].encode('utf-8') + except: + subtitle = '' + img = content['URLImage'].encode('utf-8') + url_page = content['onClick']['URLPage'].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': subtitle, + } + } + shows.append({ + 'label': title, + 'thumb': img, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_shows_3', + url_page=url_page, + title=title + ), + 'info': info + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_3': + # Check if there is any folder for this program + file_path = utils.download_catalog( + params.url_page, + '%s.json' % (params.title)) + file_shows = open(file_path).read() + shows_json = json.loads(file_shows) + + if 'strates' not in shows_json or len(shows_json['strates']) <= 2: + params.next = 'list_videos' + params.title = 'none' + params.index_page = 1 + return list_videos(params) + else: + fanart = '' + for strate in shows_json['strates']: + if strate['type'] == 'carrousel': + for content in strate['contents']: + fanart = content['URLImage'].encode('utf-8') + elif strate['type'] == 'contentRow': + title = strate['title'].encode('utf-8') + + info = { + 'video': { + 'title': title, + } + } + + shows.append({ + 'label': title, + 'fanart': fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos', + url_page=params.url_page, + title=title, + index_page=1 + ), + 'info': info + }) + + shows = common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + return shows + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + file_path = utils.download_catalog( + params.url_page, + '%s.json' % (params.url_page)) + file_videos = open(file_path).read() + videos_json = json.loads(file_videos) + + more_videos = False + no_strates = False + fanart = '' + + if 'strates' not in videos_json: + no_strates = True + else: + for strate in videos_json['strates']: + if strate['type'] == 'carrousel': + for content in strate['contents']: + fanart = content['URLImage'].encode('utf-8') + if strate['type'] == 'contentRow' or strate['type'] == 'contentGrid': + if strate['title'].encode('utf-8') == params.title or params.title == 'none': + if 'URLPage' in strate['paging']: + url = strate['paging']['URLPage'].encode('utf-8') + url = url + '&indexPage=' + params.index_page + params.index_page = int(params.index_page) + 1 + more_videos = True + file_videos = utils.get_webcontent(url) + videos_json = json.loads(file_videos) + + if more_videos or no_strates: + if len(videos_json['contents']) == 0: + more_videos = False + for content in videos_json['contents']: + title = content['title'].encode('utf-8') + try: + subtitle = content['subtitle'].encode('utf-8') + except: + subtitle = '' + img = content['URLImage'].encode('utf-8') + url_media = content['onClick']['URLPage'].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': subtitle, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + url_media=url_media, + url_page=params.url_page, + title=title, + index_page=params.index_page + ), + 'info': info, + 'is_playable': True + }) + else: + for strate in videos_json['strates']: + if strate['type'] == 'contentRow' or strate['type'] == 'contentGrid': + if strate['title'].encode('utf-8') == params.title or params.title == 'none': + for content in strate['contents']: + title = content['title'].encode('utf-8') + try: + subtitle = content['subtitle'].encode('utf-8') + except: + subtitle = '' + img = content['URLImage'].encode('utf-8') + url_media = content['onClick']['URLPage'].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': subtitle, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + url_media=url_media, + url_page=params.url_page, + title=title, + index_page=params.index_page + ), + 'info': info, + 'is_playable': True + }) + + if more_videos: + videos.append({ + 'label': common.addon.get_localized_string(30100), + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos', + url_media=url_media, + title=params.title, + url_page=params.url_page, + index_page=params.index_page + ), + + }) + + videos = common.plugin.create_listing( + videos, + content='tvshows', + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + return videos + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + file_path = utils.get_webcontent(params.url_media) + media_json = json.loads(file_path) + url = media_json['detail']['informations']['VoD']['videoURL'].encode('utf-8') + return url diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py new file mode 100755 index 0000000..b7ab8ee --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Copyright (C) 2017 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +categories = {} + +categories['Dessins animés'] = 'http://sslreplay.gulli.fr/replay/api?' \ + 'call=%7B%22api_key%22:%22iphoner_a140e' \ + 'e8cb4b10fcd8b12a7fe688b34de%22,%22method' \ + '%22:%22programme.getLatestEpisodes%22,%' \ + '22params%22:%7B%22program_image_thumb%' \ + '22:%5B310,230%5D,%22category_id%22:%22' \ + 'dessins-animes%22%7D%7D' + +categories['Émissions'] = 'https://sslreplay.gulli.fr/replay/api?' \ + 'call=%7B%22api_key%22:%22iphoner_a140e' \ + 'e8cb4b10fcd8b12a7fe688b34de%22,%22method' \ + '%22:%22programme.getLatestEpisodes%22,%' \ + '22params%22:%7B%22program_image_thumb%' \ + '22:%5B310,230%5D,%22category_id%22:%22' \ + 'emissions%22%7D%7D' + +categories['Séries & films'] = 'https://sslreplay.gulli.fr/replay/api?' \ + 'call=%7B%22api_key%22:%22iphoner_a140e' \ + 'e8cb4b10fcd8b12a7fe688b34de%22,%22method' \ + '%22:%22programme.getLatestEpisodes%22,%' \ + '22params%22:%7B%22program_image_thumb%' \ + '22:%5B310,230%5D,%22category_id%22:%22' \ + 'series%22%7D%7D' + +url_list_show = 'https://sslreplay.gulli.fr/replay/api?call=%%7B%%22api_key' \ + '%%22:%%22iphoner_a140ee8cb4b10fcd8b12a7fe688b34de%%22,%%22' \ + 'method%%22:%%22programme.getEpisodesByProgramIds%%22,%%22' \ + 'params%%22:%%7B%%22program_id_list%%22:%%5B%%22%s%%22%%5D' \ + '%%7D%%7D' +# program_id + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + # Create categories list + shows = [] + + if params.next == 'list_shows_1': + for category_title, category_url in categories.iteritems(): + shows.append({ + 'label': category_title, + 'url': common.plugin.get_url( + action='channel_entry', + category_url=category_url, + next='list_shows_cat', + title=category_title + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_cat': + file_path = utils.download_catalog( + params.category_url, + '%s_%s.json' % (params.channel_name, params.title), + random_ua=True) + file = open(file_path).read() + json_category = json.loads(file) + + for show in json_category['res']: + program_title = show['program_title'.encode('utf-8')] + program_id = show['program_id'].encode('utf-8') + fanart = show['program_image'].encode('utf-8') + + shows.append({ + 'label': program_title, + 'thumb': fanart, + 'fanart': fanart, + 'url': common.plugin.get_url( + action='channel_entry', + program_id=program_id, + next='list_videos', + title=program_title + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + + file_path = utils.download_catalog( + url_list_show % params.program_id, + '%s_%s.json' % (params.channel_name, params.program_id)) + file = open(file_path).read() + json_show = json.loads(file) + + for show in json_show['res']: + # media_id = show['media_id'].encode('utf-8') + # program_title = show['program_title'.encode('utf-8')] + # cat_id = show['cat_id'].encode('utf-8') + # program_id = show['program_id'].encode('utf-8') + fanart = show['program_image'].encode('utf-8') + thumb = show['episode_image'].encode('utf-8') + episode_title = show['episode_title'].encode('utf-8') + episode_number = show['episode_number'] + season_number = show['season_number'] + # total_episodes_in_season = show['total_episodes_in_season'] + url_ipad = show['url_ipad'].encode('utf-8') + # url_streaming = show['url_streaming'].encode('utf-8') + short_desc = show['short_desc'].encode('utf-8') + note = float(show['note'].encode('utf-8')) * 2 + date_debut = show['date_debut'].encode('utf-8') + # "2017-02-03 00:00:00" + year = int(date_debut[:4]) + day = date_debut[8:10] + month = date_debut[5:7] + date = '.'.join((day, month, str(year))) + aired = '-'.join((str(year), month, day)) + + info = { + 'video': { + 'title': episode_title, + 'plot': short_desc, + 'episode': episode_number, + 'season': season_number, + 'rating': note, + 'aired': aired, + 'date': date, + # 'duration': duration, + 'year': year, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': episode_title, + 'thumb': thumb, + 'fanart': fanart, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + url_ipad=url_ipad + ), + 'is_playable': True, + 'info': info + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE + ), + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + return params.video_urlhd diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py new file mode 100755 index 0000000..0963fb3 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Copyright (C) 2017 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +url_category_query = 'http://service.itele.fr/iphone/categorie_news?query=' + + +categories = { + 'http://service.itele.fr/iphone/topnews': 'La Une', + url_category_query + 'FRANCE': 'France', + url_category_query + 'MONDE': 'Monde', + url_category_query + 'POLITIQUE': 'Politique', + url_category_query + 'JUSTICE': 'Justice', + url_category_query + 'ECONOMIE': 'Économie', + url_category_query + 'SPORT': 'Sport', + url_category_query + 'CULTURE': 'Culture', + url_category_query + 'INSOLITE': 'Insolite' +} + +#@common.plugin.cached(common.cache_time) +def list_shows(params): + # Create categories list + shows = [] + + if params.next == 'list_shows_1': + for category_url, category_title in categories.iteritems(): + shows.append({ + 'label': category_title, + 'url': common.plugin.get_url( + action='channel_entry', + category_url=category_url, + next='list_videos_cat', + title=category_title + ) + }) + + shows.append({ + 'label': 'Les Émissions', + 'url': common.plugin.get_url( + action='channel_entry', + category_url='emissions', + next='list_shows_emissions', + title='Les Émissions' + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + elif params.next == 'list_shows_emissions': + shows.append({ + 'label': 'À la Une', + 'url': common.plugin.get_url( + action='channel_entry', + category_url='http://service.itele.fr/iphone/dernieres_emissions?query=', + next='list_videos_cat', + title='À la Une' + ) + }) + + shows.append({ + 'label': 'Magazines', + 'url': common.plugin.get_url( + action='channel_entry', + category_url='http://service.itele.fr/iphone/emissions?query=magazines', + next='list_videos_cat', + title='Magazines' + ) + }) + + shows.append({ + 'label': 'Chroniques', + 'url': common.plugin.get_url( + action='channel_entry', + category_url='http://service.itele.fr/iphone/emissions?query=chroniques', + next='list_videos_cat', + title='Chroniques' + ) + }) + + return common.plugin.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + + +def list_videos(params): + videos = [] + if params.next == 'list_videos_cat': + file_path = utils.download_catalog( + params.category_url, + '%s_%s.json' % (params.channel_name, params.title)) + file = open(file_path).read() + json_category = json.loads(file) + + if 'news' in json_category: + json_category = json_category['news'] + elif 'videos' in json_category: + json_category = json_category['videos'] + elif 'topnews' in json_category: + json_category = json_category['topnews'] + for video in json_category: + video_id = video['id_pfv'].encode('utf-8') + category = video['category'].encode('utf-8') + date_time = video['date'].encode('utf-8') # 2017-02-10 22:05:02 + title = video['title'].encode('utf-8') + description = video['description'].encode('utf-8') + thumb = video['preview169'].encode('utf-8') + video_url = video['video_urlhd'].encode('utf-8') + if not video_url: + video_url = 'no_video' + + info = { + 'video': { + 'title': title, + 'plot': description, + # 'aired': aired, + # 'date': date, + #'duration': duration, + #'year': year, + 'genre': category, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': thumb, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + video_id=video_id, + video_urlhd=video_url + ), + 'is_playable': True, + 'info': info + }) + + return common.plugin.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_GENRE, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ), + content='tvshows') + + +def get_video_URL(params): + return params.video_urlhd + diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py new file mode 100755 index 0000000..2c1ddaf --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Original work (C) JUL1EN094, SPM, SylvainCecchetto + Copyright (C) 2016 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import json +from resources.lib import utils +from resources.lib import common + +channelCatalog = 'http://pluzz.webservices.francetelevisions.fr/' \ + 'pluzz/liste/type/replay/nb/10000/chaine/%s' + +showInfo = 'http://webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/' \ + '?idDiffusion=%s&catalogue=Pluzz' + +imgURL = 'http://refonte.webservices.francetelevisions.fr%s' + +categories = {"france2": "France 2", + "france3": "France 3", + "france4": "France 4", + "france5": "France 5", + "franceo": "France Ô", + "guadeloupe": "Guadeloupe 1ère", + "guyane": "Guyane 1ère", + "martinique": "Martinique 1ère", + "mayotte": "Mayotte 1ère", + "nouvellecaledonie": "Nouvelle Calédonie 1ère", + "polynesie": "Polynésie 1ère", + "reunion": "Réunion 1ère", + "saintpierreetmiquelon": "St-Pierre et Miquelon 1ère", + "wallisetfutuna": "Wallis et Futuna 1ère", + "sport": "Sport", + "info": "Info", + "documentaire": "Documentaire", + "seriefiction": "Série & fiction", + "magazine": "Magazine", + "jeunesse": "Jeunesse", + "divertissement": "Divertissement", + "jeu": "Jeu", + "culture": "Culture"} + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_URL(params) + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + shows = [] + uniqueItem = dict() + + realChannel = params.channel_name + if params.channel_name == 'la_1ere': + realChannel = 'la_1ere_reunion%2C' \ + 'la_1ere_guyane%2C' \ + 'la_1ere_polynesie%2C' \ + 'la_1ere_martinique%2C' \ + 'la_1ere_mayotte%2C' \ + 'la_1ere_nouvellecaledonie%2C' \ + 'la_1ere_guadeloupe%2C' \ + 'la_1ere_wallisetfutuna%2C' \ + 'la_1ere_saintpierreetmiquelon' + + url_json = channelCatalog % (realChannel) + filePath = utils.download_catalog( + url_json, + '%s.json' % (params.channel_name)) + filPrgm = open(filePath).read() + jsonParser = json.loads(filPrgm) + emissions = jsonParser['reponse']['emissions'] + + if params.next == 'list_shows_1': + for emission in emissions: + rubrique = emission['rubrique'].encode('utf-8') + if rubrique not in uniqueItem: + uniqueItem[rubrique] = rubrique + rubrique_title = change_to_nicer_name(rubrique) + + shows.append({ + 'label': rubrique_title, + 'url': common.plugin.get_url( + action='channel_entry', + rubrique=rubrique, + next='list_shows_2' + ) + }) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + + shows = common.plugin.create_listing( + shows, + sort_methods=sort_methods + ) + + elif params.next == 'list_shows_2': + for emission in emissions: + rubrique = emission['rubrique'].encode('utf-8') + if rubrique == params.rubrique: + titre_programme = emission['titre_programme'].encode('utf-8') + if titre_programme != '': + id_programme = emission['id_programme'].encode('utf-8') + if id_programme == '': + id_programme = emission['id_emission'].encode('utf-8') + if id_programme not in uniqueItem: + uniqueItem[id_programme] = id_programme + icon = imgURL % (emission['image_large']) + genre = emission['genre'] + accroche_programme = emission['accroche_programme'] + + info = { + 'video': { + 'title': titre_programme, + 'plot': accroche_programme, + 'genre': genre + } + } + shows.append({ + 'label': titre_programme, + 'thumb': icon, + 'url': common.plugin.get_url( + action='channel_entry', + next='list_videos_1', + id_programme=id_programme, + ), + 'info': info + }) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + + shows = common.plugin.create_listing( + shows, + sort_methods=sort_methods + ) + + return shows + + +@common.plugin.cached(common.cache_time) +def change_to_nicer_name(original_name): + if original_name in categories: + return categories[original_name] + return original_name + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + filePath = utils.download_catalog( + channelCatalog % (params.channel_name), + '%s.json' % (params.channel_name) + ) + filPrgm = open(filePath).read() + jsonParser = json.loads(filPrgm) + emissions = jsonParser['reponse']['emissions'] + for emission in emissions: + id_programme = emission['id_programme'].encode('utf-8') + if id_programme == '': + id_programme = emission['id_emission'].encode('utf-8') + if id_programme == params.id_programme: + title = '' + plot = '' + duration = 0 + date = '' + genre = '' + id_diffusion = emission['id_diffusion'] + filPrgm = utils.get_webcontent( + showInfo % (emission['id_diffusion'])) + if(filPrgm != ''): + jsonParserShow = json.loads(filPrgm) + if jsonParserShow['synopsis']: + plot = jsonParserShow['synopsis'].encode('utf-8') + if jsonParserShow['diffusion']['date_debut']: + date = jsonParserShow['diffusion']['date_debut'] + date = date.encode('utf-8') + if jsonParserShow['real_duration']: + duration = int(jsonParserShow['real_duration']) + if jsonParserShow['titre']: + title = jsonParserShow['titre'].encode('utf-8') + if jsonParserShow['sous_titre']: + title = ' '.join(( + title, + '- [I]', + jsonParserShow['sous_titre'].encode('utf-8'), + '[/I]')) + + if jsonParserShow['genre'] != '': + genre = \ + jsonParserShow['genre'].encode('utf-8') + + year = int(date[6:10]) + day = date[:2] + month = date[3:5] + date = '.'.join((day, month, str(year))) + aired = '-'.join((str(year), month, day)) + # date : string (%d.%m.%Y / 01.01.2009) + # aired : string (2008-12-07) + image = imgURL % (jsonParserShow['image']) + info = { + 'video': { + 'title': title, + 'plot': plot, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'genre': genre, + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': image, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + id_diffusion=id_diffusion + ), + 'is_playable': True, + 'info': info + }) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ) + return common.plugin.create_listing( + videos, + sort_methods=sort_methods, + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_URL(params): + filPrgm = utils.get_webcontent(showInfo % (params.id_diffusion)) + jsonParser = json.loads(filPrgm) + url_HD = '' + url_SD = '' + for video in jsonParser['videos']: + if video['format'] == 'hls_v5_os': + url_HD = video['url'] + if video['format'] == 'm3u8-download': + url_SD = video['url'] + + desired_quality = common.plugin.get_setting( + params.channel_id + '.quality') + + if desired_quality == 'HD' and url_HD is not None: + return url_HD + else: + return url_SD diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py new file mode 100755 index 0000000..c10c181 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- +""" + Catch-up TV & More + Original work (C) JUL1EN094, SPM, SylvainCecchetto + Copyright (C) 2016 SylvainCecchetto + + This file is part of Catch-up TV & More. + + Catch-up TV & More is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Catch-up TV & More is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Catch-up TV & More; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +from bs4 import BeautifulSoup as bs +from resources.lib import utils +from resources.lib import common + +url_root = "http://www.tf1.fr/" + + +def channel_entry(params): + if 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'play' in params.next: + return get_video_url(params) + else: + return None + + +@common.plugin.cached(common.cache_time) +def list_shows(params): + shows = [] + + url = ''.join(( + url_root, + params.channel_name, + '/programmes-tv')) + file_path = utils.download_catalog( + url, + params.channel_name + '.html') + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + if params.next == 'list_shows_1': + categories_soup = root_soup.find( + 'ul', + attrs={'class': 'filters_2 contentopen'}) + for category in categories_soup.find_all('a'): + category_name = category.get_text().encode('utf-8') + category_url = category['data-target'].encode('utf-8') + + shows.append({ + 'label': category_name, + 'url': common.plugin.get_url( + action='channel_entry', + category=category_url, + next='list_shows_2')}) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL) + + shows = common.plugin.create_listing( + shows, + sort_methods=sort_methods) + + elif params.next == 'list_shows_2': + programs_soup = root_soup.find( + 'ul', + attrs={'id': 'js_filter_el_container'}) + for program in programs_soup.find_all('li'): + category = program['data-type'].encode('utf-8') + if params.category == category or params.category == 'all': + program_url = program.find( + 'div', + class_='description') + program_url = program_url.find('a')['href'].encode('utf-8') + program_name = program.find( + 'p', + class_='program').get_text().encode('utf-8') + img = program.find('img') + try: + img = img['data-srcset'].encode('utf-8') + except: + img = img['srcset'].encode('utf-8') + + img = 'http:' + img.split(',')[-1].split(' ')[0] + + shows.append({ + 'label': program_name, + 'thumb': img, + 'url': common.plugin.get_url( + action='channel_entry', + program_url=program_url, + next='list_videos')}) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL) + + shows = common.plugin.create_listing( + shows, + sort_methods=sort_methods) + + return shows + + +@common.plugin.cached(common.cache_time) +def list_videos(params): + videos = [] + + url = ''.join(( + url_root, + params.program_url, + '/videos')) + program_html = utils.get_webcontent(url) + program_soup = bs(program_html, 'html.parser') + + grid = program_soup.find( + 'ul', + class_='grid') + + for li in grid.find_all('li'): + video_type_string = li.find('strong').get_text().encode('utf-8') + video_type = video_type_string.lower() + + if 'playlist' not in video_type: + if 'replay' in video_type or \ + 'video' in video_type or \ + common.plugin.get_setting(params.channel_id + '.bonus'): + + title = li.find( + 'p', + class_='title').get_text().encode('utf-8') + + try: + stitle = li.find( + 'p', + class_='stitle').get_text().encode('utf-8') + except: + stitle = '' + + try: + duration = li.find( + 'span', + attrs={'data-format': 'duration'}) + duration = int(duration.get_text().encode('utf-8')) + except: + duration = 0 + + img = li.find('img') + try: + img = img['data-srcset'].encode('utf-8') + except: + img = img['srcset'].encode('utf-8') + + img = 'http:' + img.split(',')[-1].split(' ')[0] + + aired = li.find( + 'span', + attrs={'data-format': None, 'class': 'momentDate'}) + aired = aired.get_text().encode('utf-8') + aired = aired.split('T')[0] + + day = aired.split('-')[2] + mounth = aired.split('-')[1] + year = aired.split('-')[0] + date = '.'.join((day, mounth, year)) + # date : string (%d.%m.%Y / 01.01.2009) + # aired : string (2008-12-07) + program_id = li.find('a')['href'].encode('utf-8') + + if 'replay' not in video_type and 'video' not in video_type: + title = title + ' - [I]' + video_type_string + '[/I]' + + info = { + 'video': { + 'title': title, + 'plot': stitle, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': int(aired[:4]), + 'mediatype': 'tvshow' + } + } + + videos.append({ + 'label': title, + 'thumb': img, + 'url': common.plugin.get_url( + action='channel_entry', + next='play', + program_id=program_id, + ), + 'is_playable': True, + 'info': info + }) + + sort_methods = ( + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE, + common.sp.xbmcplugin.SORT_METHOD_UNSORTED + ) + return common.plugin.create_listing( + videos, + sort_methods=sort_methods, + content='tvshows') + + +@common.plugin.cached(common.cache_time) +def get_video_url(params): + url = url_root + params.program_id + video_html = utils.get_webcontent(url) + video_html_soup = bs(video_html, 'html.parser') + + iframe_player_soup = video_html_soup.find( + 'div', + class_='iframe_player') + + data_src = iframe_player_soup['data-src'].encode('utf-8') + + video_id = data_src[-8:] + + return 'http://wat.tv/get/ipad/' + video_id + '.m3u8' -- cgit v1.2.3