diff options
author | Razzeee <razzeee@gmail.com> | 2017-10-21 23:07:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-21 23:07:36 +0200 |
commit | 62d9a34a1f24edd48996b00bb205d0697ad01045 (patch) | |
tree | 54d23bce9438eafb58a290e7db12a90ea1e1ca3d | |
parent | 310f030f3b8bec7cbe56ece782840af347bf584a (diff) | |
parent | 6145ec6dddea5aafc7eee6260df593ea97bdd963 (diff) |
Merge pull request #1419 from SylvainCecchetto/plugin.video.catchuptvandmore
[plugin.video.catchuptvandmore] 0.1.3
131 files changed, 5766 insertions, 2303 deletions
diff --git a/plugin.video.catchuptvandmore/LICENSE.txt b/plugin.video.catchuptvandmore/LICENSE.txt index 0d6e108..0d6e108 100644..100755 --- a/plugin.video.catchuptvandmore/LICENSE.txt +++ b/plugin.video.catchuptvandmore/LICENSE.txt diff --git a/plugin.video.catchuptvandmore/README.md b/plugin.video.catchuptvandmore/README.md index c4d3ff0..fb92358 100644..100755 --- a/plugin.video.catchuptvandmore/README.md +++ b/plugin.video.catchuptvandmore/README.md @@ -10,30 +10,54 @@ Catch-Up TV & More est compatible avec la dernière version de Kodi (Kodi 17 Kry *This plugin brings together all the videos of the various services and channels of catch-up TV. Furthermore, this addon allows you to quickly access the videos and content offered by certain websites (coming soon).* ## Chaînes disponibles — *Available channels* +### Europe +- Arte *(Replay, Live TV)* +- Euronews *(Live TV)* + ### France -- TF1 -- France 2 -- France 3 -- Canal + -- France 5 -- M6 -- Arte -- C8 -- W9 -- TMC -- NT1 -- NRJ 12 -- France 4 -- BFM TV -- i-Télé -- CStar -- Gulli -- France Ô -- HD1 -- L'Équipe -- 6ter -- Numéro 23 -- Chérie 25 +##### TV +- TF1 *(Replay, Live TV)* +- France 2 *(Replay, Live TV)* +- France 3 *(Replay, Live TV)* +- Canal + *(Replay, Live TV)* +- France 5 *(Replay, Live TV)* +- M6 *(Replay)* +- C8 *(Replay, Live TV)* +- W9 *(Replay)* +- TMC *(Replay, Live TV)* +- NT1 *(Replay, Live TV)* +- NRJ 12 *(Replay, Live TV with NRJ account)* +- France 4 *(Replay, Live TV)* +- BFM TV *(Replay, Live TV)* +- CNews *(Replay, Live TV)* +- CStar *(Replay, Live TV)* +- Gulli *(Replay, Live TV)* +- France Ô *(Replay, Live TV)* +- HD1 *(Replay, Live TV)* +- L'Équipe *(Replay, Live TV)* +- 6ter *(Replay)* +- Numéro 23 *(Replay, Live TV)* +- Chérie 25 *(Replay, Live TV with NRJ account)* +- LCI *(Replay, Live TV)* +- La 1ère — Outre-Mer *(Replay)* +- France Info *(Live TV)* +- BFM Business *(Replay, Live TV)* +- RMC *(Replay, Live TV)* +- RMC Découverte *(Replay, Live TV)* +- LCP Assemblée Nationale *(Replay, Live TV)* +- France 24 *(Replay, Live TV)* +- Public Sénat *(Replay, Live TV)* + +##### Web TV +- Stories — 6play *(Replay)* +- Bruce — 6play *(Replay)* +- Crazy Kitchen — 6play *(Replay)* +- Home Time — 6play *(Replay)* +- Sixième Style — 6play *(Replay)* +- Comic — 6play *(Replay)* +- Tfou — MyTF1 *(Replay)* +- Xtra — MyTF1 *(Replay)* +- 01Net TV ### Belgique — *Belgium* - *à venir* — *coming soon* diff --git a/plugin.video.catchuptvandmore/addon.py b/plugin.video.catchuptvandmore/addon.py index 229d7d2..57eeee4 100644..100755 --- a/plugin.video.catchuptvandmore/addon.py +++ b/plugin.video.catchuptvandmore/addon.py @@ -21,20 +21,24 @@ """ import imp +import YDStreamUtils +import YDStreamExtractor from resources.lib import skeleton from resources.lib import common +YDStreamExtractor.disableDASHVideo(True) + # Useful path -lib_path = common.sp.xbmc.translatePath( +LIB_PATH = common.sp.xbmc.translatePath( common.sp.os.path.join( - common.addon.path, + common.ADDON.path, "resources", "lib")) -media_path = ( +MEDIA_PATH = ( common.sp.xbmc.translatePath( common.sp.os.path.join( - common.addon.path, + common.ADDON.path, "resources", "media" ))) @@ -42,10 +46,10 @@ media_path = ( # Initialize GNU gettext emulation in addon # This allows to use UI strings from addon’s English # strings.po file instead of numeric codes -_ = common.addon.initialize_gettext() +_ = common.ADDON.initialize_gettext() -@common.plugin.action() +@common.PLUGIN.action() def root(params): """ Build the addon main menu @@ -53,21 +57,34 @@ def root(params): """ listing = [] last_category_id = '' - for category_id, string_id in skeleton.categories.iteritems(): - if common.plugin.get_setting(category_id): + for category_id, string_id in skeleton.CATEGORIES.iteritems(): + if common.PLUGIN.get_setting(category_id): last_category_id = category_id last_window_title = _(string_id) context_menu = [] hide = ( _('Hide'), - 'XBMC.RunPlugin(' + common.plugin.get_url( + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( action='hide', item_id=category_id) + ')' ) + media_category_path = common.sp.xbmc.translatePath( + common.sp.os.path.join( + MEDIA_PATH, + 'categories', + category_id[-2:] + ) + ) + + icon = media_category_path + '.png' + fanart = media_category_path + '_fanart.png' + context_menu.append(hide) listing.append({ + 'icon': icon, + 'fanart': fanart, 'label': _(string_id), - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='list_channels', category_id=category_id, window_title=_(string_id) @@ -81,7 +98,7 @@ def root(params): params['window_title'] = last_window_title return list_channels(params) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( listing, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -89,7 +106,7 @@ def root(params): ) -@common.plugin.action() +@common.PLUGIN.action() def list_channels(params): """ Build the channels list @@ -97,12 +114,12 @@ def list_channels(params): """ # First, we sort channels by order - channels_dict = skeleton.channels[params.category_id] + channels_dict = skeleton.CHANNELS[params.category_id] channels = [] for channel_id, title in channels_dict.iteritems(): # If channel isn't disable - if common.plugin.get_setting(channel_id): - channel_order = common.plugin.get_setting(channel_id + '.order') + if common.PLUGIN.get_setting(channel_id): + channel_order = common.PLUGIN.get_setting(channel_id + '.order') channel = (channel_order, channel_id, title) channels.append(channel) @@ -114,7 +131,7 @@ def list_channels(params): # channel_id = channels.fr.6play.w9 [ channel_type, # channels - channel_country, # fr + channel_category, # fr channel_file, # 6play channel_name # w9 ] = channel_id.split('.') @@ -122,14 +139,14 @@ def list_channels(params): # channel_module = channels.fr.6play channel_module = '.'.join(( channel_type, - channel_country, + channel_category, channel_file)) media_channel_path = common.sp.xbmc.translatePath( common.sp.os.path.join( - media_path, + MEDIA_PATH, channel_type, - channel_country, + channel_category, channel_name )) @@ -138,7 +155,7 @@ def list_channels(params): item_down = ( _('Move down'), - 'XBMC.RunPlugin(' + common.plugin.get_url( + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( action='move', direction='down', channel_id_order=channel_id + '.order', @@ -146,7 +163,7 @@ def list_channels(params): ) item_up = ( _('Move up'), - 'XBMC.RunPlugin(' + common.plugin.get_url( + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( action='move', direction='up', channel_id_order=channel_id + '.order', @@ -163,7 +180,7 @@ def list_channels(params): hide = ( _('Hide'), - 'XBMC.RunPlugin(' + common.plugin.get_url( + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( action='hide', item_id=channel_id) + ')' ) @@ -176,70 +193,74 @@ def list_channels(params): 'icon': icon, 'fanart': fanart, 'label': title, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_1', + next='root', channel_name=channel_name, channel_module=channel_module, channel_id=channel_id, - channel_country=channel_country, + channel_category=channel_category, window_title=title ), 'context_menu': context_menu }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( listing, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED,) ) -@common.plugin.action() -def channel_entry(params): - """ - Last plugin action function in addon.py. - Now we are going into the channel python file. - The channel file can return folder or not item ; playable or not item - """ +def get_channel_module(params): if 'channel_name' in params and \ 'channel_module' in params and \ 'channel_id' in params and \ - 'channel_country' in params: + 'channel_category' in params: channel_name = params.channel_name channel_module = params.channel_module channel_id = params.channel_id - channel_country = params.channel_country - with common.plugin.get_storage() as storage: + channel_category = params.channel_category + with common.PLUGIN.get_storage() as storage: storage['last_channel_name'] = channel_name storage['last_channel_module'] = channel_module storage['last_channel_id'] = channel_id - storage['last_channel_country'] = channel_country + storage['last_channel_category'] = channel_category else: - with common.plugin.get_storage() as storage: + with common.PLUGIN.get_storage() as storage: channel_name = storage['last_channel_name'] channel_module = storage['last_channel_module'] channel_id = storage['last_channel_id'] - channel_country = storage['last_channel_country'] + channel_category = storage['last_channel_category'] params['channel_name'] = channel_name params['channel_id'] = channel_id - params['channel_country'] = channel_country + params['channel_category'] = channel_category channel_path = common.sp.xbmc.translatePath( common.sp.os.path.join( - lib_path, + LIB_PATH, channel_module.replace('.', '/') + '.py')) - channel = imp.load_source( + return imp.load_source( channel_name, channel_path) + +@common.PLUGIN.action() +def channel_entry(params): + """ + Last plugin action function in addon.py. + Now we are going into the channel python file. + The channel file can return folder or not item ; playable or not item + """ + channel = get_channel_module(params) + # Let's go to the channel file ... return channel.channel_entry(params) -@common.plugin.action() +@common.PLUGIN.action() def move(params): if params.direction == 'down': offset = + 1 @@ -254,29 +275,60 @@ def move(params): channel_swaped = eval(params.displayed_channels[k + offset]) channel_swaped_order = channel_swaped[0] channel_swaped_id = channel_swaped[1] - common.plugin.set_setting( + common.PLUGIN.set_setting( params.channel_id_order, channel_swaped_order) - common.plugin.set_setting( + common.PLUGIN.set_setting( channel_swaped_id + '.order', channel_order) common.sp.xbmc.executebuiltin('XBMC.Container.Refresh()') return None -@common.plugin.action() +@common.PLUGIN.action() def hide(params): - if common.plugin.get_setting('show_hidden_items_information'): + if common.PLUGIN.get_setting('show_hidden_items_information'): common.sp.xbmcgui.Dialog().ok( _('Information'), _('To re-enable hidden items go to the plugin settings')) - common.plugin.set_setting('show_hidden_items_information', False) + common.PLUGIN.set_setting('show_hidden_items_information', False) - common.plugin.set_setting(params.item_id, False) + common.PLUGIN.set_setting(params.item_id, False) common.sp.xbmc.executebuiltin('XBMC.Container.Refresh()') return None +@common.PLUGIN.action() +def download_video(params): + # Ici on a seulement le lien de la page web où se trouve la video + # Il faut appeller la fonction get_video_url de la chaine concernée pour avoir l'URL finale de la vidéo + channel = get_channel_module(params) + params.next = 'download_video' + url_video = channel.get_video_url(params) + + # Maintenant on peut télécharger la vidéo + + print 'URL_VIDEO to download ' + url_video + + vid = YDStreamExtractor.getVideoInfo(url_video, quality=3) + path = common.PLUGIN.get_setting('dlFolder') + + with YDStreamUtils.DownloadProgress() as prog: # This gives a progress dialog interface ready to use + try: + YDStreamExtractor.setOutputCallback(prog) + result = YDStreamExtractor.downloadVideo(vid, path) + if result: + # success + full_path_to_file = result.filepath + elif result.status != 'canceled': + # download failed + error_message = result.message + finally: + YDStreamExtractor.setOutputCallback(None) + + return None + + if __name__ == '__main__': window_title = common.get_window_title() - common.plugin.run(window_title) + common.PLUGIN.run(window_title) diff --git a/plugin.video.catchuptvandmore/addon.xml b/plugin.video.catchuptvandmore/addon.xml index 902f222..5e7bda0 100644..100755 --- a/plugin.video.catchuptvandmore/addon.xml +++ b/plugin.video.catchuptvandmore/addon.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="plugin.video.catchuptvandmore" name="Catch-up TV & More" - version="0.1.2" + version="0.1.3" provider-name="SylvainCecchetto"> <requires> + <!-- TODO before official repo submission: xbmc.python version="2.25.0"/> --> <import addon="xbmc.python" version="2.25.0"/> <import addon="script.module.beautifulsoup4" version="4.3.1"/> <import addon="script.module.requests" version="2.9.1"/> + <import addon="script.module.youtube.dl" version="17.518.2"/> </requires> <extension point="xbmc.python.pluginsource" library="addon.py"> <provides>video</provides> @@ -26,18 +28,38 @@ <email>catch.up.tv.and.more [AT] gmail [DOT] com</email> <source>https://github.com/SylvainCecchetto/plugin.video.catchuptvandmore</source> <news> -[Add channel] RTL-TVI -[Add channel] 6ter -[Bug] NRJ 12: No video -[Improvement] NRJ 12: Add listing for categories and seasons -[Improvement] France Télévision (pluzz): Add search feature and "last videos" categories -[Bug] TF1: Video URL failed -[Bug] Gulli: Doesn't work -[Add channel] Numéro 23 -[Add channel] Chérie 25 -[Bug] Arte: Doesn't work -[Bug] Canal+: Bug with subcategories - </news> +[Improvement] Choose video quality with DIALOG setting for compatible channels (wwark) +[Add live TV] TF1 group (wwark) +[Bug] TF1 group: Fix wrong Video URL format +[Improvement] TF1 group: Add missing date and duration for videos +[Add channel] Tfou — MyTF1 (wwark) +[Add channel] Xtra — MyTF1 (wwark) +[Add channel] LCI (wwark) +[Add Live TV] Pluzz — France Télévision (wwark) +[Add channel] La 1ère — Outre-Mer (wwark) +[Add channel] France Info (wwark) +[Add Live TV] Canal + group (wwark) +[Add channel] Stories — 6play (wwark) +[Add channel] Bruce — 6play (wwark) +[Add channel] Crazy Kitchen — 6play (wwark) +[Add channel] Home Time — 6play (wwark) +[Add channel] Sixième Style — 6play (wwark) +[Add channel] Comic — 6play (wwark) +[Add Live TV] Arte (wwark) +[Add Live TV] BFM TV (wwark) +[Add channel — Live TV] BFM Business (wwark) +[Add channel — Live TV] RMC (wwark) +[Add channel] 01Net TV (wwark) +[Add channel — Live TV] RMC Découverte (wwark) +[Add Live TV] Gulli (wwark) +[Add Live TV] L'Équipe (wwark) +[Add Live TV] Numéro 23 (wwark) +[Add channel — Live TV] LCP Assemblée Nationale (wwark) +[Add channel — Live TV] France 24 (wwark) +[Add channel — Live TV] Public Sénat (wwark) +[Add Live TV] Euronews (wwark) +[Improvement] Add download mode on multiple channels (wwark) + </news> <assets> <icon>icon.png</icon> <fanart>fanart.jpg</fanart> diff --git a/plugin.video.catchuptvandmore/fanart.jpg b/plugin.video.catchuptvandmore/fanart.jpg Binary files differindex 2d2fc2f..2d2fc2f 100644..100755 --- a/plugin.video.catchuptvandmore/fanart.jpg +++ b/plugin.video.catchuptvandmore/fanart.jpg diff --git a/plugin.video.catchuptvandmore/icon.png b/plugin.video.catchuptvandmore/icon.png Binary files differindex 53c1e7e..53c1e7e 100644..100755 --- a/plugin.video.catchuptvandmore/icon.png +++ b/plugin.video.catchuptvandmore/icon.png diff --git a/plugin.video.catchuptvandmore/resources/__init__.py b/plugin.video.catchuptvandmore/resources/__init__.py index e69de29..e69de29 100644..100755 --- a/plugin.video.catchuptvandmore/resources/__init__.py +++ b/plugin.video.catchuptvandmore/resources/__init__.py diff --git a/plugin.video.catchuptvandmore/resources/language/resource.language.en_gb/strings.po b/plugin.video.catchuptvandmore/resources/language/resource.language.en_gb/strings.po index 0b6f701..0fb703f 100644..100755 --- a/plugin.video.catchuptvandmore/resources/language/resource.language.en_gb/strings.po +++ b/plugin.video.catchuptvandmore/resources/language/resource.language.en_gb/strings.po @@ -26,9 +26,16 @@ msgid "Channels" msgstr "" msgctxt "#30002" -msgid "Quality and content" +msgid "Quality and Content" msgstr "" +msgctxt "#30003" +msgid "Download" +msgstr "" + +msgctxt "#30004" +msgid "Accounts" +msgstr "" # Settings line separators (from 30010 to 30019) msgctxt "#30010" @@ -39,6 +46,9 @@ msgctxt "#30011" msgid "Hide channels from categories" msgstr "" +msgctxt "#30012" +msgid "To configure YTDL go settings of script.module.youtube.dl" +msgstr "" # Main categories (from 30020 to 30039) msgctxt "#30020" @@ -49,6 +59,21 @@ msgctxt "#30021" msgid "Belgian channels" msgstr "" +msgctxt "#30022" +msgid "Japanese channels" +msgstr "" + +msgctxt "#30023" +msgid "European channels" +msgstr "" + +msgctxt "#30024" +msgid "United Kingdom channels" +msgstr "" + +msgctxt "#30025" +msgid "United States channels" +msgstr "" # Context menu (from 30040 to 30049) msgctxt "#30040" @@ -63,6 +88,9 @@ msgctxt "#30042" msgid "Hide" msgstr "" +msgctxt "#30043" +msgid "Download" +msgstr "" # Dialog boxes (from 30050 to 30069) msgctxt "#30050" @@ -76,80 +104,29 @@ msgstr "" # Settings quality and content (from 30070 to 30099) msgctxt "#30070" -msgid "TF1: Show bonus videos" +msgid "Video quality" msgstr "" msgctxt "#30071" -msgid "France 2: Video quality" -msgstr "" - -msgctxt "#30072" -msgid "France 3: Video quality" -msgstr "" - -msgctxt "#30073" -msgid "France 4: Video quality" -msgstr "" - -msgctxt "#30074" -msgid "France 5: Video quality" -msgstr "" - -msgctxt "#30075" -msgid "France Ô: Video quality" -msgstr "" - -msgctxt "#30076" -msgid "M6: Video quality" -msgstr "" - -msgctxt "#30077" -msgid "W9: Video quality" -msgstr "" - -msgctxt "#30078" -msgid "6ter: Video quality" -msgstr "" - -msgctxt "#30079" -msgid "Arte: Video quality" +msgid "Contents" msgstr "" msgctxt "#30080" -msgid "Arte: Language" +msgid "Arte: Choose Channel" msgstr "" msgctxt "#30081" -msgid "BFM TV: Video quality" +msgid "France24: Choose Channel" msgstr "" msgctxt "#30082" -msgid "TMC: Show bonus videos" -msgstr "" - -msgctxt "#30083" -msgid "NT1: Show bonus videos" -msgstr "" - -msgctxt "#30084" -msgid "HD1: Show bonus videos" -msgstr "" - -msgctxt "#30085" -msgid "NRJ 12: Video quality" -msgstr "" - -msgctxt "#30086" -msgid "L'Équipe: Video quality" +msgid "Euronews: Choose Channel" msgstr "" msgctxt "#30087" -msgid "TF1: Video quality" +msgid "Video quality (BEST|DEFAULT|DIALOG)" msgstr "" -msgctxt "#30088" -msgid "Numéro 23: Video quality" -msgstr "" # Others (from 30100 to 30140) msgctxt "#30100" @@ -186,4 +163,18 @@ msgstr "" msgctxt "#30108" msgid "More programs..." -msgstr ""
\ No newline at end of file +msgstr "" + +msgctxt "#30109" +msgid "Live TV" +msgstr "" + +msgctxt "#30110" +msgid "Choose video quality" +msgstr "" + +# Download (from 30200 to 30240) + +msgctxt "#30200" +msgid "Folder to Download" +msgstr "" diff --git a/plugin.video.catchuptvandmore/resources/language/resource.language.fr_fr/strings.po b/plugin.video.catchuptvandmore/resources/language/resource.language.fr_fr/strings.po index 35ee599..ee2e81c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/language/resource.language.fr_fr/strings.po +++ b/plugin.video.catchuptvandmore/resources/language/resource.language.fr_fr/strings.po @@ -26,9 +26,16 @@ msgid "Channels" msgstr "Chaînes" msgctxt "#30002" -msgid "Quality and content" -msgstr "Qualité et contenu" +msgid "Quality and Content" +msgstr "Qualité et Contenu" +msgctxt "#30003" +msgid "Download" +msgstr "Téléchargement" + +msgctxt "#30004" +msgid "Accounts" +msgstr "Comptes" # Settings line separators (from 30010 to 30019) msgctxt "#30010" @@ -39,6 +46,9 @@ msgctxt "#30011" msgid "Hide channels from categories" msgstr "Masquer des chaînes des catégories" +msgctxt "#30012" +msgid "To configure YTDL go settings of script.module.youtube.dl" +msgstr "Pour configurer YTDL aller dans la configuration de script.module.youtube.dl" # Main categories (from 30020 to 30039) msgctxt "#30020" @@ -49,6 +59,21 @@ msgctxt "#30021" msgid "Belgian channels" msgstr "Chaînes belges" +msgctxt "#30022" +msgid "Japanese channels" +msgstr "Chaînes japonaises" + +msgctxt "#30023" +msgid "European channels" +msgstr "Chaînes européennes" + +msgctxt "#30024" +msgid "United Kingdom channels" +msgstr "Chaînes anglaises" + +msgctxt "#30025" +msgid "United States channels" +msgstr "Chaînes américaines" # Context menu (from 30040 to 30049) msgctxt "#30040" @@ -63,6 +88,10 @@ msgctxt "#30042" msgid "Hide" msgstr "Masquer" +msgctxt "#30043" +msgid "Download" +msgstr "Télécharger" + # Dialog boxes (from 30050 to 30069) msgctxt "#30050" @@ -76,81 +105,28 @@ msgstr "Pour réactiver les éléments masqués rendez-vous dans les réglages d # Settings quality and content (from 30070 to 30099) msgctxt "#30070" -msgid "TF1: Show bonus videos" -msgstr "TF1 : Afficher les vidéos bonus" +msgid "Video quality" +msgstr "Qualité vidéo" msgctxt "#30071" -msgid "France 2: Video quality" -msgstr "France 2 : Qualité vidéo" - -msgctxt "#30072" -msgid "France 3: Video quality" -msgstr "France 3 : Qualité vidéo" - -msgctxt "#30073" -msgid "France 4: Video quality" -msgstr "France 4 : Qualité vidéo" - -msgctxt "#30074" -msgid "France 5: Video quality" -msgstr "France 5 : Qualité vidéo" - -msgctxt "#30075" -msgid "France Ô: Video quality" -msgstr "France Ô : Qualité vidéo" - -msgctxt "#30076" -msgid "M6: Video quality" -msgstr "M6 : Qualité vidéo" - -msgctxt "#30077" -msgid "W9: Video quality" -msgstr "W9 : Qualité vidéo" - -msgctxt "#30078" -msgid "6ter: Video quality" -msgstr "6ter : Qualité vidéo" - -msgctxt "#30079" -msgid "Arte: Video quality" -msgstr "Arte : Qualité vidéo" +msgid "Contents" +msgstr "Contenus" msgctxt "#30080" -msgid "Arte: Language" -msgstr "Arte : Langue" +msgid "Arte: Choose Channel" +msgstr "Arte : Choix de la chaîne" msgctxt "#30081" -msgid "BFM TV: Video quality" -msgstr "BFM TV : Qualité vidéo" +msgid "France24: Choose Channel" +msgstr "France24 : Choix de la chaîne" msgctxt "#30082" -msgid "TMC: Show bonus videos" -msgstr "TMC : Afficher les vidéos bonus" - -msgctxt "#30083" -msgid "NT1: Show bonus videos" -msgstr "NT1 : Afficher les vidéos bonus" - -msgctxt "#30084" -msgid "HD1: Show bonus videos" -msgstr "HD1 : Afficher les vidéos bonus" - -msgctxt "#30085" -msgid "NRJ 12: Video quality" -msgstr "NRJ 12 : Qualité vidéo" - -msgctxt "#30086" -msgid "L'Équipe: Video quality" -msgstr "L'Équipe : Qualité vidéo" +msgid "Euronews: Choose Channel" +msgstr "Euronews : Choix de la chaîne" msgctxt "#30087" -msgid "TF1: Video quality" -msgstr "TF1 : Qualité vidéo" - -msgctxt "#30088" -msgid "Numéro 23: Video quality" -msgstr "Numéro 23 : Qualité vidéo" - +msgid "Video quality (BEST|DEFAULT|DIALOG)" +msgstr "Qualité Vidéo (BEST|DEFAULT|DIALOG)" # Others (from 30100 to 30140) msgctxt "#30100" @@ -187,6 +163,20 @@ msgstr "Descendant" msgctxt "#30108" msgid "More programs..." -msgstr "Plus de programes..." +msgstr "Plus de programmes..." + +msgctxt "#30109" +msgid "Live TV" +msgstr "TV en direct" + +msgctxt "#30110" +msgid "Choose video quality" +msgstr "Choisir la qualité vidéo" + +# Download (from 30200 to 30240) + +msgctxt "#30200" +msgid "Folder to Download" +msgstr "Répertoire de téléchargement" diff --git a/plugin.video.catchuptvandmore/resources/language/resource.language.he.il/strings.po b/plugin.video.catchuptvandmore/resources/language/resource.language.he.il/strings.po new file mode 100755 index 0000000..4133130 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/language/resource.language.he.il/strings.po @@ -0,0 +1,179 @@ +# Kodi Media Center language file +# Addon Name: Catch-up TV & More +# Addon id: plugin.video.catchuptvandmore +# Addon Provider: SylvainCecchetto +msgid "" +msgstr "" +"Project-Id-Version: plugin.video.catchuptvandmore\n" +"Report-Msgid-Bugs-To: alanwww1@kodi.org\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2017-09-20 09:11+0300\n" +"Last-Translator: A. Dambledore\n" +"Language-Team: Eng2Heb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he_IL\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +# Settings categories (from 30000 to 30009) +msgctxt "#30000" +msgid "Main menu" +msgstr "תפריט ראשי" + +msgctxt "#30001" +msgid "Channels" +msgstr "ערוצים" + +msgctxt "#30002" +msgid "Quality and Content" +msgstr "איכות ותוכן" + +msgctxt "#30003" +msgid "Download" +msgstr "הורד" + +msgctxt "#30004" +msgid "Accounts" +msgstr "חשבונות" + +# Settings line separators (from 30010 to 30019) +msgctxt "#30010" +msgid "Hide main menu categories" +msgstr "הסתר קטגוריות בתפריט הראשי" + +msgctxt "#30011" +msgid "Hide channels from categories" +msgstr "הסתר ערוצים מכל הקטגוריות" + +msgctxt "#30012" +msgid "To configure YTDL go settings of script.module.youtube.dl" +msgstr "כדי לקבוע את התצורה של YTDL עבור אל ההגדרות של script.module.youtube.dl" + +# Main categories (from 30020 to 30039) +msgctxt "#30020" +msgid "French channels" +msgstr "ערוצים צרפתיים" + +msgctxt "#30021" +msgid "Belgian channels" +msgstr "ערוצים בלגיים" + +msgctxt "#30022" +msgid "Japanese channels" +msgstr "ערוצים יפניים" + +msgctxt "#30023" +msgid "European channels" +msgstr "ערוצים אירופיים" + +msgctxt "#30024" +msgid "United Kingdom channels" +msgstr "ערוצים אנגליים" + +msgctxt "#30025" +msgid "United States channels" +msgstr "ערוצים אמריקאיים" + +# Context menu (from 30040 to 30049) +msgctxt "#30040" +msgid "Move down" +msgstr "רד למטה" + +msgctxt "#30041" +msgid "Move up" +msgstr "עבור למעלה" + +msgctxt "#30042" +msgid "Hide" +msgstr "הסתר" + +msgctxt "#30043" +msgid "Download" +msgstr "הורד" + +# Dialog boxes (from 30050 to 30069) +msgctxt "#30050" +msgid "Information" +msgstr "מידע" + +msgctxt "#30051" +msgid "To re-enable hidden items go to the plugin settings" +msgstr "כדי להפעיל מחדש את הפריטים המוסתרים, עבור אל ההגדרות של תוסף" + + +# Settings quality and content (from 30070 to 30099) +msgctxt "#30070" +msgid "Video quality" +msgstr "איכות וידאו מיו-טיוב" + +msgctxt "#30071" +msgid "Contents" +msgstr "תוכן העניינים" + +msgctxt "#30080" +msgid "Arte: Choose Channel" +msgstr "Arte: בחר ערוץ" + +msgctxt "#30081" +msgid "France24: Choose Channel" +msgstr "France24: בחר ערוץ" + +msgctxt "#30082" +msgid "Euronews: Choose Channel" +msgstr "Euronews: בחר ערוץ" + +msgctxt "#30087" +msgid "Video quality (BEST|DEFAULT|DIALOG)" +msgstr "איכות וידאו (הטוב ביותר|ברירת מחדל|תיבת דו-שיח)" + + +# Others (from 30100 to 30140) +msgctxt "#30100" +msgid "More videos..." +msgstr "קטעי וידאו נוספים..." + +msgctxt "#30101" +msgid "All videos" +msgstr "נגן את כל הסרטונים" + +msgctxt "#30102" +msgid "DRM protected video" +msgstr "וידאו מוגן DRM" + +msgctxt "#30103" +msgid "Search" +msgstr "חיפוש" + +msgctxt "#30104" +msgid "Last videos" +msgstr "קטעי וידאו אחרונים" + +msgctxt "#30105" +msgid "From A to Z" +msgstr "מ-א עד ת" + +msgctxt "#30106" +msgid "Ascending" +msgstr "בסדר עולה" + +msgctxt "#30107" +msgid "Descending" +msgstr "בסדר יורד" + +msgctxt "#30108" +msgid "More programs..." +msgstr "עוד תוכניות..." + +msgctxt "#30109" +msgid "Live TV" +msgstr "טלוויזיה חיה" + +msgctxt "#30110" +msgid "Choose video quality" +msgstr "בחר איכות וידאו" + +# Download (from 30200 to 30240) +msgctxt "#30200" +msgid "Folder to Download" +msgstr "תיקיה להורדה" diff --git a/plugin.video.catchuptvandmore/resources/lib/__init__.py b/plugin.video.catchuptvandmore/resources/lib/__init__.py index e69de29..e69de29 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/__init__.py +++ b/plugin.video.catchuptvandmore/resources/lib/__init__.py diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/__init__.py b/plugin.video.catchuptvandmore/resources/lib/channels/__init__.py index e69de29..e69de29 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/__init__.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/__init__.py diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/eu/__init__.py b/plugin.video.catchuptvandmore/resources/lib/channels/eu/__init__.py new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/eu/__init__.py diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py b/plugin.video.catchuptvandmore/resources/lib/channels/eu/arte.py index 02aa6c4..9fe6d0b 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/arte.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/eu/arte.py @@ -24,48 +24,88 @@ import json from resources.lib import utils from resources.lib import common -# TODO +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +# TO DO # List emissions # Most recent # Most viewed -url_replay = 'https://www.arte.tv/papi/tvguide/videos/' \ +URL_REPLAY = 'https://www.arte.tv/papi/tvguide/videos/' \ 'ARTE_PLUS_SEVEN/%s.json?includeLongRights=true' -# Valid languages: F or D +# Langue, ... +URL_LIVE_ARTE = 'https://api.arte.tv/api/player/v1/livestream/%s' +# Langue, ... def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: return get_video_url(params) + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) - -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build categories listing""" shows = [] emissions_list = [] categories = {} - desired_language = common.plugin.get_setting( + desired_language = common.PLUGIN.get_setting( params.channel_id + '.language') - if desired_language == 'Auto': - if params.channel_country == 'fr': - desired_language = 'F' - elif params.channel_country == 'de': - desired_language = 'D' - elif desired_language == 'fr': - desired_language = 'F' - elif desired_language == 'de': + if desired_language == 'DE': desired_language = 'D' else: desired_language = 'F' file_path = utils.download_catalog( - url_replay % desired_language, + URL_REPLAY % desired_language, '%s_%s.json' % (params.channel_name, desired_language) ) file_replay = open(file_path).read() @@ -103,14 +143,14 @@ def list_shows(params): emissions_list.append(emission_dict) - with common.plugin.get_storage() as storage: + with common.PLUGIN.get_storage() as storage: storage['emissions_list'] = emissions_list for category in categories.keys(): shows.append({ 'label': category, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos_cat', category=category, @@ -118,7 +158,7 @@ def list_shows(params): ), }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -127,10 +167,11 @@ def list_shows(params): ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] - with common.plugin.get_storage() as storage: + with common.PLUGIN.get_storage() as storage: emissions_list = storage['emissions_list'] if params.next == 'list_videos_cat': @@ -165,19 +206,31 @@ def list_videos(params): } } + # Nouveau pour ajouter le menu pour télécharger la vidéo + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url=emission['video_url']) + ')' + ) + context_menu.append(download_video) + # Fin + videos.append({ 'label': title, 'thumb': emission['image'], - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', + next='play_r', url=emission['video_url'], ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu # A ne pas oublier pour ajouter le bouton "Download" à chaque vidéo }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_DATE, @@ -189,59 +242,102 @@ def list_videos(params): ), content='tvshows') +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] -@common.plugin.cached(common.cache_time) -def get_video_url(params): - file_medias = utils.get_webcontent( - params.url) - json_parser = json.loads(file_medias) + desired_language = common.PLUGIN.get_setting( + params.channel_id + '.language') - url_auto = '' - url_hd_plus = '' - url_hd = '' - url_sd = '' - url_sd_minus = '' - video_streams = json_parser['videoJsonPlayer']['VSR'] + if desired_language == 'DE': + desired_language = 'de' + else: + desired_language = 'fr' - if 'HLS_SQ_1' in video_streams: - url_auto = video_streams['HLS_SQ_1']['url'].encode('utf-8') + url_live = '' - if 'HTTP_MP4_SQ_1' in video_streams: - url_hd_plus = video_streams['HTTP_MP4_SQ_1']['url'].encode('utf-8') + file_path = utils.download_catalog( + URL_LIVE_ARTE % desired_language, + '%s_%s_live.json' % (params.channel_name, desired_language) + ) + file_live = open(file_path).read() + json_parser = json.loads(file_live) + + title = json_parser["videoJsonPlayer"]["VTI"].encode('utf-8') + img = json_parser["videoJsonPlayer"]["VTU"]["IUR"].encode('utf-8') + plot = '' + if 'V7T' in json_parser["videoJsonPlayer"]: + plot = json_parser["videoJsonPlayer"]["V7T"].encode('utf-8') + elif 'VDE' in json_parser["videoJsonPlayer"]: + plot = json_parser["videoJsonPlayer"]["VDE"].encode('utf-8') + duration = 0 + duration = json_parser["videoJsonPlayer"]["videoDurationSeconds"] + url_live = json_parser["videoJsonPlayer"]["VSR"]["HLS_SQ_1"]["url"] + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) - if 'HTTP_MP4_EQ_1' in video_streams: - url_hd = video_streams['HTTP_MP4_EQ_1']['url'].encode('utf-8') +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + file_medias = utils.get_webcontent( + params.url) + json_parser = json.loads(file_medias) - if 'HTTP_MP4_HQ_1' in video_streams: - url_sd = video_streams['HTTP_MP4_HQ_1']['url'].encode('utf-8') + url_selected = '' + video_streams = json_parser['videoJsonPlayer']['VSR'] - if 'HTTP_MP4_MQ_1' in video_streams: - url_sd_minus = video_streams['HTTP_MP4_MQ_1']['url'].encode('utf-8') + desired_quality = common.PLUGIN.get_setting('quality') - desired_quality = common.plugin.get_setting( - params.channel_id + '.quality') + if desired_quality == "DIALOG": + all_datas_videos = [] - if desired_quality == 'Auto' and url_auto: - return url_auto + for video in video_streams: + if not video.find("HLS"): + datas = json_parser['videoJsonPlayer']['VSR'][video] + new_list_item = common.sp.xbmcgui.ListItem() + new_list_item.setLabel(datas['mediaType'] + " (" + datas['versionLibelle'] + ")") + new_list_item.setPath(datas['url']) + all_datas_videos.append(new_list_item) - if desired_quality == 'HD+' and url_hd_plus: - return url_hd_plus - elif url_hd: - return url_hd + seleted_item = common.sp.xbmcgui.Dialog().select("Choose Stream", all_datas_videos) - if desired_quality == 'HD' and url_hd: - return url_hd - elif url_hd_plus: - return url_hd_plus + url_selected = all_datas_videos[seleted_item].getPath().encode('utf-8') - if desired_quality == 'SD' and url_sd: - return url_sd - elif url_sd_minus: - return url_sd_minus + elif desired_quality == "BEST": + url_selected = video_streams['HTTP_MP4_SQ_1']['url'].encode('utf-8') + else: + url_selected = video_streams['HLS_SQ_1']['url'].encode('utf-8') - if desired_quality == 'SD-' and url_sd_minus: - return url_sd_minus - elif url_sd: - return url_sd + return url_selected + elif params.next == 'play_l': + return params.url - return url_auto diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/eu/euronews.py b/plugin.video.catchuptvandmore/resources/lib/channels/eu/euronews.py new file mode 100755 index 0000000..be0edad --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/eu/euronews.py @@ -0,0 +1,193 @@ +# -*- 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 + +# TO DO +# Replay add emissions +# Add info LIVE TV + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_LIVE_API = 'http://%s.euronews.com/api/watchlive.json' +# Language + +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + modes = [] + + # Add Replay Desactiver + if params.channel_name != 'euronews': + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_shows(params): + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_videos(params): + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + desired_language = common.PLUGIN.get_setting( + params.channel_id + '.language') + + if desired_language == 'FR': + title = '%s Français Live' % (params.channel_name.upper()) + elif desired_language == 'EN': + title = '%s English Live' % (params.channel_name.upper()) + elif desired_language == 'AR': + title = '%s عربية Live' % (params.channel_name.upper()) + elif desired_language == 'DE': + title = '%s Deutsch Live' % (params.channel_name.upper()) + elif desired_language == 'IT': + title = '%s Italiano Live' % (params.channel_name.upper()) + elif desired_language == 'ES': + title = '%s Español Live' % (params.channel_name.upper()) + elif desired_language == 'PT': + title = '%s Português Live' % (params.channel_name.upper()) + elif desired_language == 'RU': + title = '%s Русский Live' % (params.channel_name.upper()) + elif desired_language == 'TR': + title = '%s Türkçe Live' % (params.channel_name.upper()) + elif desired_language == 'FA': + title = '%s فارسی Live' % (params.channel_name.upper()) + elif desired_language == 'GR': + title = '%s Ελληνικά Live' % (params.channel_name.upper()) + elif desired_language == 'HU': + title = '%s Magyar Nyelv Live' % (params.channel_name.upper()) + + if desired_language == 'EN': + url_live_json = URL_LIVE_API % 'www' + elif desired_language == 'AR': + url_live_json = URL_LIVE_API % 'arabic' + else: + url_live_json = URL_LIVE_API % desired_language.lower() + + file_path = utils.download_catalog( + url_live_json, + '%s_%s_live.json' % (params.channel_name,desired_language.lower()) + ) + json_live = open(file_path).read() + json_parser = json.loads(json_live) + url_2nd_json = json_parser["url"] + + file_path_2 = utils.download_catalog( + url_2nd_json, + '%s_%s_live_2.json' % (params.channel_name,desired_language.lower()) + ) + json_live_2 = open(file_path_2).read() + json_parser_2 = json.loads(json_live_2) + + url_live = json_parser_2["primary"] + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + + if params.next == 'play_l': + return params.url diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py index 4a62a9d..b779d94 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/6play.py @@ -26,64 +26,112 @@ import json from resources.lib import utils from resources.lib import common +# TO DO +# LIVE TV protected by #EXT-X-FAXS-CM +# https://helpx.adobe.com/adobe-media-server/dev/configuring-content-protection-hls.html + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() # 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_ROOT = 'http://pc.middleware.6play.fr/6play/v2/platforms/' \ + 'm6group_web/services/%s/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/' \ +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/' \ +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/' \ +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/' \ +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/' \ +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' +URL_IMG = 'https://images.6play.fr/v1/images/%s/raw' def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: - return get_video_URL(params) + return get_video_url(params) + return None + + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build categories listing""" shows = [] if params.next == 'list_shows_1': + + url_root_site = '' + if params.channel_name == 'stories' or params.channel_name == 'bruce' \ + or params.channel_name == 'crazy_kitchen' or params.channel_name == 'home' \ + or params.channel_name == 'styles' or params.channel_name == 'comedy': + url_root_site = URL_ROOT % params.channel_name + else: + url_root_site = URL_ROOT % (params.channel_name + 'replay') + file_path = utils.download_catalog( - url_root % (params.channel_name), + url_root_site, '%s.json' % (params.channel_name), random_ua=True) file_prgm = open(file_path).read() @@ -102,7 +150,7 @@ def list_shows(params): category_name = array['name'].encode('utf-8') shows.append({ 'label': category_name, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', category_id=category_id, next='list_shows_2', @@ -111,7 +159,7 @@ def list_shows(params): ) }) - shows = common.plugin.create_listing( + shows = common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -121,7 +169,7 @@ def list_shows(params): elif params.next == 'list_shows_2': file_prgm = utils.get_webcontent( - url_category % (params.category_id), + URL_CATEGORY % (params.category_id), random_ua=True) json_parser = json.loads(file_prgm) @@ -131,13 +179,14 @@ def list_shows(params): program_desc = array['description'].encode('utf-8') program_imgs = array['images'] program_img = '' + program_fanart = '' 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) + 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) + program_fanart = URL_IMG % (external_key) info = { 'video': { @@ -149,7 +198,7 @@ def list_shows(params): 'label': program_title, 'thumb': program_img, 'fanart': program_fanart, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_shows_3', program_id=program_id, @@ -162,7 +211,7 @@ def list_shows(params): 'info': info }) - shows = common.plugin.create_listing( + shows = common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -172,10 +221,16 @@ def list_shows(params): elif params.next == 'list_shows_3': program_json = utils.get_webcontent( - url_subcategory % (params.program_id), + URL_SUBCATEGORY % (params.program_id), random_ua=True) json_parser = json.loads(program_json) + + try: + program_fanart = params.program_fanart + except: + program_fanart = '' + for sub_category in json_parser['program_subcats']: sub_category_id = str(sub_category['id']) sub_category_title = sub_category['title'].encode('utf-8') @@ -190,8 +245,8 @@ def list_shows(params): shows.append({ 'label': sub_category_title, 'thumb': params.program_img, - 'fanart': params.program_fanart, - 'url': common.plugin.get_url( + 'fanart': program_fanart, + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos', program_id=params.program_id, @@ -203,15 +258,15 @@ def list_shows(params): info = { 'video': { - 'title': common.addon.get_localized_string(30101), + 'title': common.ADDON.get_localized_string(30101), 'plot': params.program_desc } } shows.append({ - 'label': common.addon.get_localized_string(30101), + 'label': common.ADDON.get_localized_string(30101), 'thumb': params.program_img, - 'fanart': params.program_fanart, - 'url': common.plugin.get_url( + 'fanart': program_fanart, + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos', program_id=params.program_id, @@ -222,7 +277,7 @@ def list_shows(params): 'info': info }) - shows = common.plugin.create_listing( + shows = common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -233,14 +288,15 @@ def list_shows(params): return shows -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] if params.sub_category_id == 'null': - url = url_videos2 % params.program_id + url = URL_VIDEOS2 % params.program_id else: - url = url_videos % (params.program_id, params.sub_category_id) + url = URL_VIDEOS % (params.program_id, params.sub_category_id) program_json = utils.get_webcontent( url, random_ua=True) @@ -275,7 +331,7 @@ def list_videos(params): 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) + program_img = URL_IMG % (external_key) info = { 'video': { @@ -289,19 +345,29 @@ def list_videos(params): } } + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + video_id=video_id) + ')' + ) + context_menu.append(download_video) + videos.append({ 'label': title, 'thumb': program_img, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', next='play', video_id=video_id, ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_DATE, @@ -312,10 +378,11 @@ def list_videos(params): content='tvshows') -@common.plugin.cached(common.cache_time) -def get_video_URL(params): +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" video_json = utils.get_webcontent( - url_json_video % (params.video_id), + URL_JSON_VIDEO % (params.video_id), random_ua=True) json_parser = json.loads(video_json) @@ -343,10 +410,10 @@ def get_video_URL(params): manifest_url, random_ua=True) if 'drm' in manifest: - utils.send_notification(common.addon.get_localized_string(30102)) + utils.send_notification(common.ADDON.get_localized_string(30102)) return '' - desired_quality = common.plugin.get_setting( + desired_quality = common.PLUGIN.get_setting( params.channel_id + '.quality') if desired_quality == 'Auto': @@ -370,16 +437,9 @@ def get_video_URL(params): 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 + desired_quality = common.PLUGIN.get_setting('quality') - elif desired_quality == 'Force SD': - if url_ultra_sd: - return url_ultra_sd - elif url_sd: - return url_sd + if (desired_quality == 'BEST' or desired_quality == 'DIALOG') and url_ultra_hd: + return url_ultra_hd + else: 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 index e69de29..e69de29 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/__init__.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/__init__.py diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py index 7bd7a93..e52cbf4 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/bfmtv.py @@ -21,214 +21,740 @@ ''' import json +import ast +import time +import re +from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -import ast -url_token = 'http://api.nextradiotv.com/bfmtv-applications/' +# TO DO +# Add Live TV (ONENET ???) -url_menu = 'http://www.bfmtv.com/static/static-mobile/bfmtv/' \ +# BFMTV, RMC, ONENET, etc ... +URL_TOKEN = 'http://api.nextradiotv.com/%s-applications/' +#channel + +URL_MENU = 'http://www.bfmtv.com/static/static-mobile/bfmtv/' \ 'ios-smartphone/v0/configuration.json' -url_replay = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ +URL_REPLAY = 'http://api.nextradiotv.com/%s-applications/%s/' \ 'getPage?pagename=replay' -# token +# channel, token -url_show = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ +URL_SHOW = 'http://api.nextradiotv.com/%s-applications/%s/' \ 'getVideosList?category=%s&count=100&page=%s' -# token, category, page_number +# channel, token, category, page_number -url_video = 'http://api.nextradiotv.com/bfmtv-applications/%s/' \ +URL_VIDEO = 'http://api.nextradiotv.com/%s-applications/%s/' \ 'getVideo?idVideo=%s' -# token, video_id +# channel, token, video_id + +# URL Live +# Channel ONENET +URL_LIVE_ONENET = 'http://www.01net.com/mediaplayer/live-video/' + +# Channel BFMTV +URL_LIVE_BFMTV = 'http://www.bfmtv.com/mediaplayer/live-video/' + +URL_LIVE_BFM_PARIS = 'http://www.bfmtv.com/mediaplayer/live-bfm-paris/' + +# Channel BFM Business +URL_LIVE_BFMBUSINESS = 'http://bfmbusiness.bfmtv.com/mediaplayer/live-video/' + +# Channel RMC +URL_LIVE_BFM_SPORT = 'http://rmcsport.bfmtv.com/mediaplayer/live-bfm-sport/' + +# RMC Decouverte +URL_REPLAY_RMCDECOUVERTE = 'http://rmcdecouverte.bfmtv.com/mediaplayer-replay/' + +URL_VIDEO_HTML_RMCDECOUVERTE = 'http://rmcdecouverte.bfmtv.com/mediaplayer-replay/?id=%s' +# VideoId_html + +URL_LIVE_RMCDECOUVERTE = 'http://rmcdecouverte.bfmtv.com/mediaplayer-direct/' + +URL_JS_POLICY_KEY = 'http://players.brightcove.net/%s/%s_default/index.min.js' +# AccountId, PlayerId + +URL_VIDEO_JSON_BRIGHTCOVE = 'https://edge.api.brightcove.com/playback/v1/accounts/%s/videos/%s' +# AccountId, VideoId +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() -@common.plugin.cached(common.cache_time) -def get_token(): - file_token = utils.get_webcontent(url_token) +@common.PLUGIN.cached(common.CACHE_TIME) +def get_token(channel_name): + """Get session token""" + file_token = utils.get_webcontent(URL_TOKEN % (channel_name)) token_json = json.loads(file_token) return token_json['session']['token'].encode('utf-8') +@common.PLUGIN.cached(common.CACHE_TIME) +def get_policy_key(data_account, data_player): + """Get policy key""" + file_js = utils.get_webcontent(URL_JS_POLICY_KEY % (data_account, data_player)) + return re.compile('policyKey:"(.+?)"').findall(file_js)[0] + + def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) if 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: - return get_video_URL(params) + return get_video_url(params) + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay Desactiver + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + if params.channel_name != '01net': + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): - # Create categories list + """Build categories listing""" shows = [] - if params.next == 'list_shows_1': + if params.channel_name == 'rmcdecouverte': + 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') + URL_REPLAY_RMCDECOUVERTE, + '%s_replay.html' % (params.channel_name)) + program_html = open(file_path).read() + + program_soup = bs(program_html, 'html.parser') + videos_soup = program_soup.find_all( + 'article', + class_='art-c modulx2-5 bg-color-rub0-1 box-shadow relative') + for video in videos_soup: + video_id = video.find('figure').find('a')['href'].split('&', 1)[0].rsplit('=', 1)[1] + video_img = video.find('figure').find('a').find('img')['data-original'] + video_titles = video.find( + 'div', class_="art-body" + ).find('a').find('h2').get_text().encode( + 'utf-8' + ).replace('\n', ' ').replace('\r', ' ').split(' ') + video_title = '' + for i in video_titles: + video_title = video_title + ' ' + i.strip() shows.append({ - 'label': title, - 'thumb': image_url, - 'url': common.plugin.get_url( + 'label': video_title, + 'thumb': video_img, + 'url': common.PLUGIN.get_url( action='channel_entry', - category=category, next='list_videos_1', - title=title, + video_id=video_id, + title=video_title, page='1', - window_title=title + window_title=video_title ) }) - return common.plugin.create_listing( - shows, - sort_methods=( - common.sp.xbmcplugin.SORT_METHOD_UNSORTED, - common.sp.xbmcplugin.SORT_METHOD_LABEL - ) + else: + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + URL_REPLAY % (params.channel_name, get_token(params.channel_name)), + '%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', + window_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) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] - if 'previous_listing' in params: - videos = ast.literal_eval(params['previous_listing']) - if params.next == 'list_videos_1': + if params.channel_name == 'rmcdecouverte': 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 + URL_VIDEO_HTML_RMCDECOUVERTE % (params.video_id), + '%s_%s_replay.html' % (params.channel_name, params.video_id)) + video_html = open(file_path).read() + + video_soup = bs(video_html, 'html.parser') + data_video_soup = video_soup.find('div', class_='next-player') + + data_account = data_video_soup['data-account'] + data_video_id = data_video_soup['data-video-id'] + data_player = data_video_soup['data-player'] + + # Method to get JSON from 'edge.api.brightcove.com' + file_json = utils.download_catalog( + URL_VIDEO_JSON_BRIGHTCOVE % (data_account, data_video_id), + '%s_%s_replay.json' % (data_account, data_video_id), + force_dl=False, + request_type='get', + post_dic={}, + random_ua=False, + specific_headers={'Accept': 'application/json;pk=%s' % ( + get_policy_key(data_account, data_player))}, + params={}) + video_json = open(file_json).read() + json_parser = json.loads(video_json) + + + video_title = '' + program_title = '' + for program in json_parser["tags"]: + program_title = program.upper() + ' - ' + video_title = program_title + json_parser["name"].encode('utf-8').lower() + video_img = '' + for poster in json_parser["poster_sources"]: + video_img = poster["src"] + video_plot = json_parser["long_description"].encode('utf-8') + video_duration = 0 + video_duration = json_parser["duration"] / 1000 + video_url = '' + for url in json_parser["sources"]: + if 'type' in url: + video_url = url["src"].encode('utf-8') + + date_value_list = json_parser["published_at"].split('T')[0].split('-') + + day = date_value_list[2] + mounth = date_value_list[1] + year = date_value_list[0] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': video_title, + 'aired': aired, + 'date': date, + 'duration': video_duration, + 'plot': video_plot, + 'year': year, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + video_id=params.video_id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': video_title, + 'thumb': video_img, + 'fanart': video_img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + video_url=video_url + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + else: + if 'previous_listing' in params: + videos = ast.literal_eval(params['previous_listing']) + + if params.next == 'list_videos_1': + file_path = utils.download_catalog( + URL_SHOW % ( + params.channel_name, + get_token(params.channel_name), + 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 + + value_date = time.strftime('%d %m %Y', time.localtime(video["begin_date"])) + date = str(value_date).split(' ') + day = date[0] + mounth = date[1] + year = date[2] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': title, + 'plot': description, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'genre': category, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + video_id=video_id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': image, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + video_id=video_id, + video_id_ext=video_id_ext + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + # 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), + window_title=params.window_title, + update_listing=True, + previous_listing=str(videos) + ) + + }) + + 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', + update_listing='update_listing' in params, + ) + + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + if params.channel_name == 'rmcdecouverte': + + file_path = utils.download_catalog( + URL_LIVE_RMCDECOUVERTE, + '%s_live.html' % (params.channel_name)) + live_html = open(file_path).read() + + live_soup = bs(live_html, 'html.parser') + data_live_soup = live_soup.find('div', class_='next-player') + + data_account = data_live_soup['data-account'] + data_video_id = data_live_soup['data-video-id'] + data_player = data_live_soup['data-player'] + + # Method to get JSON from 'edge.api.brightcove.com' + file_json = utils.download_catalog( + URL_VIDEO_JSON_BRIGHTCOVE % (data_account, data_video_id), + '%s_%s_live.json' % (data_account, data_video_id), + force_dl=False, + request_type='get', + post_dic={}, + random_ua=False, + specific_headers={'Accept': 'application/json;pk=%s' % ( + get_policy_key(data_account, data_player))}, + params={}) + video_json = open(file_json).read() + json_parser = json.loads(video_json) + + title = json_parser["name"] + plot = json_parser["long_description"].encode('utf-8') + + for url in json_parser["sources"]: + url_live = url["src"].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live, + ), + 'is_playable': True, + 'info': info + }) + + else: + + if params.channel_name == 'bfmtv': + + # BFMTV + file_path = utils.download_catalog( + URL_LIVE_BFMTV, + '%s_live.html' % (params.channel_name)) + live_html = open(file_path).read() + + url_live = re.compile(r'file: \'(.*?)\'').findall(live_html)[0] + + title = '%s Live' % params.channel_name.upper() info = { 'video': { 'title': title, - 'plot': description, - #'aired': aired, - #'date': date, - 'duration': duration, - #'year': year, - 'genre': category, - 'mediatype': 'tvshow' + 'plot': plot, + 'duration': duration } } - videos.append({ + lives.append({ 'label': title, - 'thumb': image, - 'url': common.plugin.get_url( + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( action='channel_entry', - next='play', - video_id=video_id, - video_id_ext=video_id_ext + next='play_l', + url_live=url_live, ), '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), - window_title=params.window_title, - update_listing=True, - previous_listing=str(videos) - ) + #BFM PARIS + file_paris_path = utils.download_catalog( + URL_LIVE_BFM_PARIS, + 'bfm_paris_live.html') + live_paris_html = open(file_paris_path).read() + + live_paris_soup = bs(live_paris_html, 'html.parser') + data_live_paris_soup = live_paris_soup.find('div', class_='BCLvideoWrapper') + + data_account_paris = data_live_paris_soup.find('script')['data-account'] + data_video_id_paris = data_live_paris_soup.find('script')['data-video-id'] + data_player_paris = data_live_paris_soup.find('script')['data-player'] + + # Method to get JSON from 'edge.api.brightcove.com' + file_json_paris = utils.download_catalog( + URL_VIDEO_JSON_BRIGHTCOVE % (data_account_paris, data_video_id_paris), + '%s_%s_live.json' % (data_account_paris, data_video_id_paris), + force_dl=False, + request_type='get', + post_dic={}, + random_ua=False, + specific_headers={'Accept': 'application/json;pk=%s' % ( + get_policy_key(data_account_paris, data_player_paris))}, + params={}) + video_json_paris = open(file_json_paris).read() + json_parser_paris = json.loads(video_json_paris) + + title_paris = json_parser_paris["name"] + plot_paris = '' + if json_parser_paris["long_description"]: + plot_paris = json_parser_paris["long_description"].encode('utf-8') + + for url_paris in json_parser_paris["sources"]: + url_live_paris = url_paris["src"].encode('utf-8') + + info_paris = { + 'video': { + 'title': title_paris, + 'plot': plot_paris, + 'duration': duration + } + } - }) + lives.append({ + 'label': title_paris, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live_paris, + ), + 'is_playable': True, + 'info': info_paris + }) - 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', - update_listing='update_listing' in params, - ) + elif params.channel_name == 'bfmbusiness': + + #BFM BUSINESS + file_path = utils.download_catalog( + URL_LIVE_BFMBUSINESS, + '%s_live.html' % (params.channel_name)) + live_html = open(file_path).read() + + live_soup = bs(live_html, 'html.parser') + data_live_soup = live_soup.find('div', class_='BCLvideoWrapper') + + data_account = data_live_soup.find('script')['data-account'] + data_video_id = data_live_soup.find('script')['data-video-id'] + data_player = data_live_soup.find('script')['data-player'] + + # Method to get JSON from 'edge.api.brightcove.com' + file_json = utils.download_catalog( + URL_VIDEO_JSON_BRIGHTCOVE % (data_account, data_video_id), + '%s_%s_live.json' % (data_account, data_video_id), + force_dl=False, + request_type='get', + post_dic={}, + random_ua=False, + specific_headers={'Accept': 'application/json;pk=%s' % ( + get_policy_key(data_account, data_player))}, + params={}) + video_json = open(file_json).read() + json_parser = json.loads(video_json) + + title = json_parser["name"] + plot = '' + if json_parser["long_description"]: + plot = json_parser["long_description"].encode('utf-8') + + for url in json_parser["sources"]: + url_live = url["src"].encode('utf-8') + img = json_parser["poster"].encode('utf-8') + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } -@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 + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live, + ), + 'is_playable': True, + 'info': info + }) + + elif params.channel_name == 'rmc': + + #BFM SPORT + file_path = utils.download_catalog( + URL_LIVE_BFM_SPORT, + 'bfm_sport_live.html') + live_html = open(file_path).read() + + live_soup = bs(live_html, 'html.parser') + + data_live_soup = live_soup.find('div', class_='BCLvideoWrapper') + + data_account = data_live_soup.find('script')['data-account'] + data_video_id = data_live_soup.find('script')['data-video-id'] + data_player = data_live_soup.find('script')['data-player'] + + # Method to get JSON from 'edge.api.brightcove.com' + file_json = utils.download_catalog( + URL_VIDEO_JSON_BRIGHTCOVE % (data_account, data_video_id), + '%s_%s_live.json' % (data_account, data_video_id), + force_dl=False, + request_type='get', + post_dic={}, + random_ua=False, + specific_headers={'Accept': 'application/json;pk=%s' % ( + get_policy_key(data_account, data_player))}, + params={}) + video_json = open(file_json).read() + json_parser = json.loads(video_json) + + title = json_parser["name"] + plot = '' + if json_parser["long_description"]: + plot = json_parser["long_description"].encode('utf-8') + + for url in json_parser["sources"]: + url_live = url["src"].encode('utf-8') + break + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live, + ), + 'is_playable': True, + 'info': info + }) + + elif params.channel_name == '01net': + + # TO DO + + return None + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_l': + return params.url_live + elif params.channel_name == 'rmcdecouverte' and params.next == 'play_r': + return params.video_url + elif params.channel_name == 'rmcdecouverte' and params.next == 'download_video': + return URL_VIDEO_HTML_RMCDECOUVERTE % (params.video_id) + elif params.channel_name != 'rmcdecouverte' and (params.next == 'play_r' or params.next == 'download_video'): + file_medias = utils.get_webcontent( + URL_VIDEO % (params.channel_name, get_token(params.channel_name), params.video_id)) + json_parser = json.loads(file_medias) + + if params.next == 'download_video': + return json_parser['video']['long_url'].encode('utf-8') + + video_streams = json_parser['video']['medias'] + + desired_quality = common.PLUGIN.get_setting('quality') + + if desired_quality == "DIALOG": + all_datas_videos = [] + for datas in video_streams: + new_list_item = common.sp.xbmcgui.ListItem() + new_list_item.setLabel( + "Video Height : " + str(datas['frame_height']) + \ + " (Encoding : " + str(datas['encoding_rate']) + ")" + ) + new_list_item.setPath(datas['video_url']) + all_datas_videos.append(new_list_item) + + seleted_item = common.sp.xbmcgui.Dialog().select("Choose Stream", all_datas_videos) + + return all_datas_videos[seleted_item].getPath().encode('utf-8') + + elif desired_quality == 'BEST': + #GET LAST NODE (VIDEO BEST QUALITY) + url_best_quality = '' + for datas in video_streams: + url_best_quality = datas['video_url'].encode('utf-8') + return url_best_quality + else: + #DEFAULT VIDEO + return json_parser['video']['video_url'].encode('utf-8') diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py deleted file mode 100644 index 07bd241..0000000 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/c.py +++ /dev/null @@ -1,210 +0,0 @@ -# -*- 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, - window_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, - window_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 deleted file mode 100644 index d0e7dff..0000000 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/canalplus.py +++ /dev/null @@ -1,407 +0,0 @@ -# -*- 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 -import ast - - -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): - shows = [] - if params.next == 'list_shows_1': - if 'url_page' not in params: - params.url_page = url_categories % get_token() - if 'title' not in params: - params.title = 'root' - if 'fanart' in params: - fanart = params.fanart - else: - fanart = '' - - file_path = utils.download_catalog( - params.url_page, - '%s_%s_%s.json' % ( - params.channel_name, - params.title, - common.sp.md5(params.url_page).hexdigest())) - file_shows = open(file_path).read() - shows_json = json.loads(file_shows) - if 'strates' in shows_json: - strates = shows_json['strates'] - if len(strates) == 1 and 'textList_like' not in params: - params['title'] = strates[0]['title'].encode('utf-8') - params['next'] = 'list_shows_2' - return list_shows(params) - elif len(strates) == 2 and 'textList_like' not in params: - for strate in strates: - if strate['type'].encode('utf-8') != 'carrousel': - params['title'] = strate['title'].encode('utf-8') - params['next'] = 'list_shows_2' - return list_shows(params) - - for strate in strates: - if strate['type'] == 'carrousel': - for content in strate['contents']: - fanart = content['URLImage'].encode('utf-8') - # Main categories e.g. Séries, Humour, Sport - if 'textList_like' in params and params.textList_like is True: - if 'title' in strate and \ - strate['title'].encode('utf-8') == params.title: - for content in strate['contents']: - title = content['title'].encode('utf-8') - url_page = content[ - 'onClick']['URLPage'].encode('utf-8') - try: - subtitle = content['subtitle'].encode('utf-8') - except: - subtitle = '' - try: - img = content['URLImage'].encode('utf-8') - except: - img = '' - - info = { - 'video': { - 'title': title, - 'plot': subtitle, - } - } - - shows.append({ - 'label': title, - 'thumb': img, - 'url': common.plugin.get_url( - action='channel_entry', - url_page=url_page, - next='list_shows_1', - title=title, - window_title=title, - fanart=fanart - ), - 'info': info - }) - else: - if strate['type'] == 'textList': - for content in strate['contents']: - title = content['title'].encode('utf-8') - url_page = content[ - 'onClick']['URLPage'].encode('utf-8') - try: - subtitle = content['subtitle'].encode('utf-8') - except: - subtitle = '' - try: - img = content['URLImage'].encode('utf-8') - except: - img = '' - - info = { - 'video': { - 'title': title, - 'plot': subtitle, - } - } - - shows.append({ - 'label': title, - 'thumb': img, - 'url': common.plugin.get_url( - action='channel_entry', - url_page=url_page, - next='list_shows_1', - title=title, - window_title=title, - fanart=fanart - ), - 'info': info - }) - # Videos, e.g. "Ne manquez pas" - elif strate['type'] == 'contentGrid': - title = strate['title'].encode('utf-8') - shows.append({ - 'label': title, - 'url': common.plugin.get_url( - action='channel_entry', - url_page=params.url_page, - next='list_shows_2', - title=title, - window_title=title, - ) - }) - # Other levels (subcategories, ...) e.g. "Top emissions" - elif strate['type'] == 'contentRow': - title = strate['title'].encode('utf-8') - shows.append({ - 'label': title, - 'url': common.plugin.get_url( - action='channel_entry', - url_page=params.url_page, - next='list_shows_2', - title=title, - window_title=title, - ) - }) - elif 'textList_like' not in params: - for content in shows_json['contents']: - title = content['title'].encode('utf-8') - params['title'] = title - params['next'] = 'list_shows_2' - return list_shows(params) - - else: - for content in shows_json['contents']: - title = content['title'].encode('utf-8') - url_page = content[ - 'onClick']['URLPage'].encode('utf-8') - try: - subtitle = content['subtitle'].encode('utf-8') - except: - subtitle = '' - try: - img = content['URLImage'].encode('utf-8') - except: - img = '' - - info = { - 'video': { - 'title': title, - 'plot': subtitle, - } - } - - shows.append({ - 'label': title, - 'thumb': img, - 'url': common.plugin.get_url( - action='channel_entry', - url_page=url_page, - next='list_shows_1', - title=title, - window_title=title, - fanart=fanart - ), - 'info': info - }) - - 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': - file_path = utils.download_catalog( - params.url_page, - '%s_%s_%s.json' % ( - params.channel_name, - params.title, - common.sp.md5(params.url_page).hexdigest())) - file_shows = open(file_path).read() - shows_json = json.loads(file_shows) - - if 'strates' in shows_json: - strates = shows_json['strates'] - for strate in strates: - if 'title' in strate and \ - strate['title'].encode('utf-8') == params.title: - contents = strate['contents'] - else: - contents = shows_json['contents'] - for content in contents: - if 'type' in content and \ - content['type'].encode('utf-8') == 'quicktime': - return list_videos(params) - else: - params['textList_like'] = True - params['title'] = params.title - params['next'] = 'list_shows_1' - return list_shows(params) - - -@common.plugin.cached(common.cache_time) -def list_videos(params): - videos = [] - if 'previous_listing' in params: - videos = ast.literal_eval(params['previous_listing']) - file_path = utils.download_catalog( - params.url_page, - '%s_%s_%s.json' % ( - params.channel_name, - params.title, - common.sp.md5(params.url_page).hexdigest())) - file_videos = open(file_path).read() - videos_json = json.loads(file_videos) - more_videos = True - fanart = '' - - if 'strates' in videos_json: - for strate in videos_json['strates']: - if strate['type'] == 'carrousel': - for content in strate['contents']: - fanart = content['URLImage'].encode('utf-8') - - # Check if we are in the correct cotegory - if 'title' in strate and \ - strate['title'].encode('utf-8') == params.title: - - # If we have lot of videos ... - if 'URLPage' in strate['paging']: - url = strate['paging']['URLPage'].encode('utf-8') - url = url + '&indexPage=1' - params['url_page'] = url - params['fanart'] = fanart - return list_videos(params) - - # Else show only this videos - else: - 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 - ), - 'info': info, - 'is_playable': True - }) - else: - 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': params.fanart, - 'url': common.plugin.get_url( - action='channel_entry', - next='play', - url_media=url_media, - title=title, - fanart=params.fanart - ), - 'info': info, - 'is_playable': True - }) - - if more_videos is True: - # More videos... - current_index_page = int(params.url_page[-1]) - videos.append({ - 'fanart': params.fanart, - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( - action='channel_entry', - next='list_videos', - title=params.title, - url_page=params.url_page[:-1] + str( - current_index_page + 1), - update_listing=True, - previous_listing=str(videos), - fanart=params.fanart - ), - - }) - - return common.plugin.create_listing( - videos, - content='tvshows', - sort_methods=( - common.sp.xbmcplugin.SORT_METHOD_UNSORTED, - common.sp.xbmcplugin.SORT_METHOD_LABEL - ), - update_listing='update_listing' in params - ) - - -@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/france24.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/france24.py new file mode 100755 index 0000000..6d61ec9 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/france24.py @@ -0,0 +1,294 @@ +# -*- 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 time +import re +import json +from bs4 import BeautifulSoup as bs +from resources.lib import utils +from resources.lib import common + +# TO DO +# Replay (emission) | (just 5 first episodes) Add More Button (with api) to download just some part ? (More Work TO DO) +# Add info LIVE TV (picture, plot) +# Add Video, Last JT, Last ECO, Last Meteo +# Select Language settings not show + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_LIVE_SITE = 'http://www.france24.com/%s/' +# Language + +URL_INFO_LIVE = 'http://www.france24.com/%s/_fragment/player/nowplaying/' +# Language + +URL_API_VOD = 'http://api.france24.com/%s/services/json-rpc/emission_list?databases=f24%s&key=XXX' \ + '&start=0&limit=50&edition_start=0&edition_limit=5' +# language + +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_shows(params): + """Build shows listing""" + shows = [] + + desired_language = common.PLUGIN.get_setting( + params.channel_id + '.language') + + if params.next == 'list_shows_1': + file_path = utils.download_catalog( + URL_API_VOD % (desired_language.lower(),desired_language.lower()), + '%s_%s_vod.json' % (params.channel_name,desired_language.lower()) + ) + json_vod = open(file_path).read() + json_parser = json.loads(json_vod) + + list_caterories = json_parser["result"]["f24%s" % desired_language.lower()]["list"] + for category in list_caterories: + + category_name = category["title"].encode('utf-8') + img = category["image"][0]["original"].encode('utf-8') + nid = category["nid"] + url = category["url"].encode('utf-8') + + shows.append({ + 'label': category_name, + 'fanart': img, + 'thumb': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_videos_cat', + nid=nid, + url=url, + window_title=category_name, + category_name=category_name, + ) + }) + + 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): + """Build videos listing""" + videos = [] + + desired_language = common.PLUGIN.get_setting( + params.channel_id + '.language') + + file_path = utils.download_catalog( + URL_API_VOD % (desired_language.lower(), desired_language.lower()), + '%s_%s_vod.json' % (params.channel_name, desired_language.lower()) + ) + json_vod = open(file_path).read() + json_parser = json.loads(json_vod) + + list_caterories = json_parser["result"]["f24%s" % desired_language.lower()]["list"] + for category in list_caterories: + if str(params.nid) == str(category["nid"]): + for video in category["editions"]["list"]: + + title = video["title"].encode('utf-8') + plot = video["intro"].encode('utf-8') + img = video["image"][0]["original"].encode('utf-8') + url = video["video"][0]["mp4-mbr"].encode('utf-8') + + value_date = time.strftime('%d %m %Y', time.localtime(int(video["created"]))) + date = str(value_date).split(' ') + day = date[0] + mounth = date[1] + year = date[2] + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': title, + 'aired': aired, + 'date': date, + #'duration': video_duration, + 'year': year, + 'plot' : plot, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url=url) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url=url + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + + # TO DO add More button Video + + return common.PLUGIN.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE + ), + content='tvshows') + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + desired_language = common.PLUGIN.get_setting( + params.channel_id + '.language') + + url_live = URL_LIVE_SITE % desired_language.lower() + + file_path = utils.download_catalog( + url_live, + '%s_%s_live.html' % (params.channel_name, desired_language.lower()) + ) + html_live = open(file_path).read() + root_soup = bs(html_live, 'html.parser') + + json_parser = json.loads(root_soup.select_one("script[type=application/json]").text) + media_datas_list = json_parser['medias']['media']['media_sources']['media_source'] + for datas in media_datas_list: + if datas['source']: + url_live = datas['source'] + + live_info = utils.get_webcontent(URL_INFO_LIVE % (desired_language.lower())) + title = re.compile('id="main-player-playing-value">(.+?)<').findall(live_info)[0] + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_l': + return params.url + elif params.next == 'play_r' or params.next == 'download_video': + return params.url + diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/groupecanal.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/groupecanal.py new file mode 100755 index 0000000..f2e5f84 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/groupecanal.py @@ -0,0 +1,699 @@ +# -*- 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 re +import json +import ast +from bs4 import BeautifulSoup as bs +from resources.lib import utils +from resources.lib import common + + +# TO DO +# Replay (More Refactoring todo) / Find API for all channel (JSON) get Replay/Live ? +# Get URL Live FROM SITE +# QUALITY +# Add Button "More Videos" + +# URL : + +URL_ROOT_SITE = 'http://www.%s.fr' +# Channel + +# Live : +URL_LIVE_CPLUS = 'http://www.canalplus.fr/pid3580-live-tv-clair.html' +URL_LIVE_C8 = 'http://www.c8.fr/pid5323-c8-live.html' +URL_LIVE_CSTAR = 'http://www.cstar.fr/pid5322-cstar-live.html' +URL_LIVE_CNEWS = 'http://www.cnews.fr/direct' + +# Replay Cplus : +URL_ROOT_CPLUS = 'http://www.canalplus.fr' + +URL_LIST_EMISSIONS_CPLUS = 'http://www.canalplus.fr/pid8034-les-emissions-de-canal.html' + +# Replay C8 & CStar +URL_REPLAY_C8__CSTAR_ROOT = 'http://lab.canal-plus.pro/web/app_prod.php/api/replay/%s' +# Channel id : +# c8 : 1 +# cstar : 2 +URL_REPLAY_C8__CSTAR_SHOWS = 'http://lab.canal-plus.pro/web/app_prod.php/api/pfv/list/%s/%s' +# channel_id/show_id + +# Replay CNews +URL_VIDEOS_CNEWS = URL_ROOT_SITE + '/videos/' + +URL_EMISSIONS_CNEWS = URL_ROOT_SITE + '/emissions' + +# Replay/Live => Parameters Channel, VideoId +URL_INFO_CONTENT = 'http://service.canal-plus.com/video/rest/getvideos/%s/%s?format=json' + +CHANNEL_NAME_CATALOG = { + 'cplus': 'cplus', + 'c8': 'd8', + 'cstar': 'd17', + 'cnews': 'itele' +} + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + return None + +def get_token(): + """Get session token""" + token_json = utils.get_webcontent(URL_REPLAY_CPLUS_AUTH) + token_json = json.loads(token_json) + token = token_json['token'] + return token + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_channel_id(params): + """Get channel id by name""" + if params.channel_name == 'c8': + return '1' + elif params.channel_name == 'cstar': + return '2' + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : _('Live TV'), + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_shows(params): + """Create categories list""" + shows = [] + + ################### BEGIN CNEWS ########################### + if params.next == 'list_shows_1' and params.channel_name == 'cnews': + + file_path = utils.download_catalog( + URL_VIDEOS_CNEWS % params.channel_name, + '%s_categories.html' % ( + params.channel_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + menu_soup = root_soup.find('div', class_="nav-tabs-inner") + + categories_soup = menu_soup.find_all('a') + + for category in categories_soup: + + category_name = category.get_text().encode('utf-8') + category_url = (URL_ROOT_SITE % params.channel_name) + category.get('href') + + if category_name != 'Les tops': + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + category_name=category_name, + next='list_shows_2', + window_title=category_name + ) + }) + + elif params.next == 'list_shows_2' and params.channel_name == 'cnews': + + if params.category_name == 'Les sujets': + + file_path = utils.download_catalog( + params.category_url, + '%s_%s.html' % ( + params.channel_name,params.category_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + categories_soup = root_soup.find_all('a', class_="checkbox") + + for category in categories_soup: + + category_name = category.get_text().encode('utf-8') + category_url = (URL_ROOT_SITE % params.channel_name) + category.get('href') + + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + page="1", + category_name=category_name, + next='list_videos', + window_title=category_name + ) + }) + else: + # Find all emissions + file_path = utils.download_catalog( + (URL_EMISSIONS_CNEWS % params.channel_name), + '%s_ALL_EMISSION.html' % ( + params.channel_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + categories_soup = root_soup.find_all('article', class_="item") + + for category in categories_soup: + + category_name = category.find('h3').get_text().encode('utf-8') + category_url = (URL_VIDEOS_CNEWS % params.channel_name) + '/emissions' + category.find('a').get('href').split('.fr')[1] + category_img = category.find('img').get('src').encode('utf-8') + + shows.append({ + 'label': category_name, + 'thumb': category_img, + 'fanart': category_img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + page="1", + category_name=category_name, + next='list_videos', + window_title=category_name + ) + }) + + + ################### END CNEWS ########################### + + ################### BEGIN C8 and CStar ################## + elif params.next == 'list_shows_1' and (params.channel_name == 'c8' or \ + params.channel_name == 'cstar'): + file_path = utils.download_catalog( + URL_REPLAY_C8__CSTAR_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, + window_title=title + ) + }) + + elif params.next == 'list_shows_2' and (params.channel_name == 'c8' or \ + params.channel_name == 'cstar'): + # Create category's programs list + file_path = utils.download_catalog( + URL_REPLAY_C8__CSTAR_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_cat', + id=id, + videos_recent=videos_recent, + slug=slug, + title=title, + window_title=title + ) + }) + ################### END C8 and CStar ################## + + ################### BEGIN CANAL + ################## + elif params.next == 'list_shows_1' and params.channel_name == 'cplus': + + file_path = utils.download_catalog( + URL_LIST_EMISSIONS_CPLUS, + '%s_categories.html' % ( + params.channel_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + categories_soup = root_soup.find_all('div', class_='cell') + + for category in categories_soup: + + category_name = category.find('h6').get_text().encode('utf-8') + category_url = URL_ROOT_CPLUS + category.find('a').get('href') + category_img = category.find('img').get('src').encode('utf-8') + + if category_name != 'Les tops': + shows.append({ + 'label': category_name, + 'thumb': category_img, + 'fanart': category_img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + category_name=category_name, + next='list_shows_2', + window_title=category_name + ) + }) + + elif params.next == 'list_shows_2' and params.channel_name == 'cplus': + + file_path = utils.download_catalog( + params.category_url, + '%s_%s.html' % ( + params.channel_name,params.category_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + sections_soup = root_soup.find('div', class_="listeRegroupee") + + list_section = sections_soup.find_all('h2') + for section in list_section: + section = section.get_text().encode('utf-8') + + shows.append({ + 'label': section, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=params.category_url, + category_name=params.category_name, + category_section=section, + next='list_videos', + window_title=section + ) + }) + + ################### END CANAL + ################## + + 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): + """Build videos listing""" + videos = [] + if 'previous_listing' in params: + videos = ast.literal_eval(params['previous_listing']) + + ################### BEGIN CNEWS ########################### + if params.channel_name == 'cnews': + + url_page = params.category_url + '/page/%s' % params.page + + file_path = utils.download_catalog( + url_page, + '%s_%s_%s.html' % (params.channel_name, params.category_name, params.page)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + programs = root_soup.find_all('article', class_='item') + + for program in programs: + title = program.find('h3').get_text().encode('utf-8') + thumb = program.find('img').get('src').encode('utf-8') + #Get Video_ID + video_html = utils.get_webcontent(program.find('a').get('href').encode('utf-8')) + id = re.compile(r'videoId=(.*?)"').findall(video_html)[0] + #Get Description + datas_video = bs(video_html, 'html.parser') + description = datas_video.find('article', class_='entry-body').get_text().encode('utf-8') + duration = 0 + + date = re.compile(r'property="video:release_date" content="(.*?)"').findall(video_html)[0].split('T')[0].split('-') + day = date[2] + mounth = date[1] + year = date[0] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': title, + 'plot': description, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + #'genre': category, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + id=id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': thumb, + 'fanart': thumb, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + id=id + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + # More videos... + videos.append({ + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=params.category_url, + category_name=params.category_name, + next='list_videos', + page=str(int(params.page) + 1), + update_listing=True, + previous_listing=str(videos) + ), + }) + ################### END CNEWS ########################### + + ################### BEGIN C8 and CStar ################## + elif params.channel_name == 'c8' or params.channel_name == 'cstar': + file_path = utils.download_catalog( + URL_REPLAY_C8__CSTAR_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' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + id=id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': thumb, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + id=id, + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + ################### END C8 and CStar ################## + + ################### BEGIN Canal + ################## + elif params.channel_name == 'cplus': + + file_path = utils.download_catalog( + params.category_url, + '%s_%s_%s.html' % (params.channel_name, params.category_name, params.category_section)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + sections_soup = root_soup.find('div', class_="listeRegroupee") + + i = 0 + j = 0 + list_sections = sections_soup.find_all('h2') + for section in list_sections: + i = i + 1 + if section.get_text().encode('utf-8') == params.category_section: + break + + videos_sections_soup = sections_soup.find_all('ul', class_="features features-alt features-alt-videov3-4x3 features-alt-videov3-4x3-noMarge") + for videos_section in videos_sections_soup: + j = j + 1 + if i == j: + data_videos = videos_section.find_all('li') + + for data_video in data_videos: + + title = data_video.find('h4').get('title').encode('utf-8') + description = data_video.find('p').find('a').get_text().strip().encode('utf-8') + duration = 0 + thumb = data_video.find('img').get('src').encode('utf-8') + id = data_video.get('id').split('_')[1] + + info = { + 'video': { + 'title': title, + 'plot': description, + #'aired': aired, + #'date': date, + 'duration': duration, + #'year': year, + #'genre': category, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + id=id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': thumb, + 'fanart': thumb, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + id=id + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + ################### END Canal + ################## + + 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', + update_listing='update_listing' in params, + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + url_live_html = '' + if params.channel_name == 'cplus': + url_live_html = URL_LIVE_CPLUS + elif params.channel_name == 'c8': + url_live_html = URL_LIVE_C8 + elif params.channel_name == 'cstar': + url_live_html = URL_LIVE_CSTAR + elif params.channel_name == 'cnews': + url_live_html = URL_LIVE_CNEWS + + file_path_html = utils.download_catalog( + url_live_html, + '%s_live.html' % (params.channel_name) + ) + html_live = open(file_path_html).read() + + video_id_re = '' + + if params.channel_name == 'cnews': + video_id_re = re.compile(r'content: \'(.*?)\'').findall(html_live) + else : + video_id_re = re.compile(r'\bdata-video="(?P<video_id>[0-9]+)"').findall(html_live) + + file_path_json = utils.download_catalog( + URL_INFO_CONTENT % (CHANNEL_NAME_CATALOG[params.channel_name], video_id_re[0]), + '%s_%s_live.json' % (CHANNEL_NAME_CATALOG[params.channel_name], video_id_re[0]) + ) + file_live_json = open(file_path_json).read() + json_parser = json.loads(file_live_json) + + title = json_parser["INFOS"]["TITRAGE"]["TITRE"].encode('utf-8') + plot = json_parser["INFOS"]["DESCRIPTION"].encode('utf-8') + img = json_parser["MEDIA"]["IMAGES"]["GRAND"].encode('utf-8') + url_live = json_parser["MEDIA"]["VIDEOS"]["IPAD"].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + file_video = utils.get_webcontent( + URL_INFO_CONTENT % (CHANNEL_NAME_CATALOG[params.channel_name],params.id) + ) + media_json = json.loads(file_video) + return media_json['MEDIA']['VIDEOS']['HLS'].encode('utf-8') + # Live CPlus, C8, CStar and CNews + elif params.next == 'play_l': + return params.url diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py index ac6986d..79dedad 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/gulli.py @@ -20,72 +20,125 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +import re import json +import time +from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -import time +# TO DO +# Improve Live TV (Title, picture, plot) -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) +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() +SECRET_KEY = '19nBVBxv791Xs' -secret_key = '19nBVBxv791Xs' - - -def get_api_key(): - date = time.strftime("%Y%m%d") - key = secret_key + date - key = common.sp.md5(key).hexdigest() - return 'iphoner_' + key +CATEGORIES = {} - -categories = {} - -categories['Dessins animés'] = 'http://sslreplay.gulli.fr/replay/api?' \ +CATEGORIES['Dessins animés'] = 'http://sslreplay.gulli.fr/replay/api?' \ 'call=%%7B%%22api_key%%22:%%22%s%%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?' \ +CATEGORIES['Émissions'] = 'https://sslreplay.gulli.fr/replay/api?' \ 'call=%%7B%%22api_key%%22:%%22%s%%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?' \ +CATEGORIES['Séries & films'] = 'https://sslreplay.gulli.fr/replay/api?' \ 'call=%%7B%%22api_key%%22:%%22%s%%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' \ +URL_LIST_SHOW = 'https://sslreplay.gulli.fr/replay/api?call=%%7B%%22api_key' \ '%%22:%%22%s%%22,%%22' \ 'method%%22:%%22programme.getEpisodesByProgramIds%%22,%%22' \ 'params%%22:%%7B%%22program_id_list%%22:%%5B%%22%s%%22%%5D' \ '%%7D%%7D' + +URL_LIVE_TV = 'http://replay.gulli.fr/Direct' + # program_id +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + return None + + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_api_key(): + """Compute the API key""" + date = time.strftime("%Y%m%d") + key = SECRET_KEY + date + key = common.sp.md5(key).hexdigest() + return 'iphoner_' + key + -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): - # Create categories list + """Build categories listing""" shows = [] if params.next == 'list_shows_1': - for category_title, category_url in categories.iteritems(): + for category_title, category_url in CATEGORIES.iteritems(): shows.append({ 'label': category_title, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', category_url=category_url % get_api_key(), next='list_shows_cat', @@ -94,7 +147,7 @@ def list_shows(params): ) }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -119,7 +172,7 @@ def list_shows(params): 'label': program_title, 'thumb': fanart, 'fanart': fanart, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', program_id=program_id, next='list_videos', @@ -128,7 +181,7 @@ def list_shows(params): ) }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -137,12 +190,13 @@ def list_shows(params): ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] file_path = utils.download_catalog( - url_list_show % (get_api_key(), params.program_id), + URL_LIST_SHOW % (get_api_key(), params.program_id), '%s_%s.json' % (params.channel_name, params.program_id)) file = open(file_path).read() json_show = json.loads(file) @@ -185,20 +239,30 @@ def list_videos(params): } } + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_streaming=url_streaming) + ')' + ) + context_menu.append(download_video) + videos.append({ 'label': episode_title, 'thumb': thumb, 'fanart': fanart, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', + next='play_r', url_streaming=url_streaming ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -208,14 +272,87 @@ def list_videos(params): content='tvshows') -@common.plugin.cached(common.cache_time) -def get_video_URL(params): - url_root = params.url_streaming.replace('playlist.m3u8', '') - m3u8_content = utils.get_webcontent(params.url_streaming) - last_url = '' +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + file_path = utils.download_catalog( + URL_LIVE_TV, + params.channel_name + '_live.html') + root_live_html = open(file_path).read() + root_live_soup = bs(root_live_html, 'html.parser') + + live_soup = root_live_soup.find( + 'div', + class_='wrapperVideo' + ) + + url_live_embeded = '' + for live in live_soup.find_all('iframe'): + url_live_embeded = live.get('src').encode('utf-8') + + file_path_2 = utils.download_catalog( + url_live_embeded, + params.channel_name + '_live_embeded.html') + root_live_embeded_html = open(file_path_2).read() + + all_url_video = re.compile(r'file: \'(.*?)\'').findall(root_live_embeded_html) + + for url_video in all_url_video: + if url_video.count('m3u8') > 0: + url_live = url_video + + title = '%s Live' % params.channel_name.upper() + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + url_root = params.url_streaming.replace('playlist.m3u8', '') + m3u8_content = utils.get_webcontent(params.url_streaming) + last_url = '' + + for line in m3u8_content.splitlines(): + if 'm3u8' in line and 'video' in line: + last_url = line - for line in m3u8_content.splitlines(): - if 'm3u8' in line and 'video' in line: - last_url = line + return url_root + last_url - return url_root + last_url + elif params.next == 'play_l': + return params.url_live diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py deleted file mode 100644 index 3b32c65..0000000 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/itele.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- 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, - window_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', - window_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', - window_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', - window_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', - window_title='Chroniques' - ) - }) - - 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_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 - date_time = date_time.split(' ')[0] - date_splited = date_time.split('-') - year = date_splited[0] - mounth = date_splited[1] - day = date_splited[2] - aired = '-'.join((year, mounth, day)) - date = '.'.join((day, mounth, year)) - # date : string (%d.%m.%Y / 01.01.2009) - # aired : string (2008-12-07) - 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/lcp.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/lcp.py new file mode 100755 index 0000000..e1065d9 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/lcp.py @@ -0,0 +1,594 @@ +# -*- 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 re +import ast +import json +from bs4 import BeautifulSoup as bs +from resources.lib import utils +from resources.lib import common + +# TO DO +# Use some API to simplify +# Add info LIVE TV + +# LCP contient deux sources de video pour les replays +# New : play1.qbrick.com +# Old : www.dailymotion.com + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_ROOT = 'http://www.lcp.fr' + +URL_LIVE_SITE = 'http://www.lcp.fr/le-direct' + +URL_DAILYMOTION_EMBED = 'http://www.dailymotion.com/embed/video/%s' + +URL_VIDEO_REPLAY = 'http://play1.qbrick.com/config/avp/v1/player/media/%s/darkmatter/%s/' +#VideoID, AccountId + +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + +CATEGORIES = { + 'http://www.lcp.fr/actualites' : 'Actualités', + 'http://www.lcp.fr/emissions' : 'Émissions', + 'http://www.lcp.fr/documentaires' : 'Documentaires' +} + +CORRECT_MOUNTH = { + 'janvier' : '01', + 'février' : '02', + 'mars' : '03', + 'avril' : '04', + 'mai' : '05', + 'juin' : '06', + 'juillet' : '07', + 'août' : '08', + 'septembre' : '09', + 'octobre' : '10', + 'novembre' : '11', + 'décembre' : '12' +} + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay Desactiver + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_shows(params): + """Build shows listing""" + shows = [] + + if params.next == 'list_shows_1': + + for category_url, category_name in CATEGORIES.iteritems(): + + if category_name == 'Émissions': + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + category_name=category_name, + next='list_shows_2', + window_title=category_name + ) + }) + elif category_name == 'Actualités': + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + actualites_url=category_url, + actualites_name=category_name, + page='0', + next='list_videos_actualites', + window_title=category_name + ) + }) + elif category_name == 'Documentaires': + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + documentaires_url=category_url, + documentaires_name=category_name, + page='0', + next='list_videos_documentaires', + window_title=category_name + ) + }) + + elif params.next == 'list_shows_2': + + file_path = utils.download_catalog( + params.category_url, + '%s_%s.html' % ( + params.channel_name, + params.category_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + emissions_soup = root_soup.find_all('div',class_='content') + + for emission in emissions_soup: + + emission_name = emission.find('h2').get_text().encode('utf-8') + emission_img = emission.find('img')['src'].encode('utf-8') + emission_url = URL_ROOT + emission.find('a')['href'].encode('utf-8') + + shows.append({ + 'label': emission_name, + 'thumb': emission_img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + emission_url=emission_url, + emission_name=emission_name, + page='0', + next='list_videos_emissions', + window_title=emission_name + ) + }) + + 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): + """Build videos listing""" + videos = [] + + if 'previous_listing' in params: + videos = ast.literal_eval(params['previous_listing']) + + if params.next == 'list_videos_documentaires': + + if params.page == 0: + url = params.documentaires_url + else: + url = params.documentaires_url + '?page=' + str(params.page) + + file_path = utils.download_catalog( + url, + '%s_%s_%s.html' % ( + params.channel_name, + params.documentaires_name, + params.page)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + video_soup = root_soup.find_all('div', class_="node node-lcp-tv-episode node-teaser clearfix") + + for video in video_soup: + + title = video.find('h2').find('a').get_text().encode('utf-8') + value_date = video.find('div', class_="content").find('span', class_="date").get_text().encode('utf-8') + date = value_date.split(' ') + day = date[0] + try: + mounth = CORRECT_MOUNTH[date[1]] + except: + mounth = '00' + year = date[2] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + duration = 0 + duration = int(video.find('div', class_="content").find('div', class_="duration").find('div').find('span').get_text()) * 60 + img = video.find('a').find('img')['src'].encode('utf-8') + url_video = URL_ROOT + video['about'].encode('utf-8') + + + info = { + 'video': { + 'title': title, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'mediatype': 'tvshow' + } + } + + # Nouveau pour ajouter le menu pour télécharger la vidéo + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url_video) + ')' + ) + context_menu.append(download_video) + # Fin + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url_video=url_video + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu # A ne pas oublier pour ajouter le bouton "Download" à chaque vidéo + }) + + # More videos... + videos.append({ + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( + action='channel_entry', + documentaires_url=params.documentaires_url, + documentaires_name=params.documentaires_name, + next='list_videos_documentaires', + page=str(int(params.page) + 1), + update_listing=True, + previous_listing=str(videos) + ), + }) + + elif params.next == 'list_videos_actualites': + + if params.page == 0: + url = params.actualites_url + else: + url = params.actualites_url + '?page=' + str(params.page) + + file_path = utils.download_catalog( + url, + '%s_%s_%s.html' % ( + params.channel_name, + params.actualites_name, + params.page)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + video_soup = root_soup.find_all('div', class_="node node-lcp-reportage node-promoted node-teaser actu-teaser clearfix") + + for video in video_soup: + + title = video.find('h2').find('a').get_text().encode('utf-8') + aired = video.find('div', class_="content").find('div', class_="field field_submitted").get_text() + date = '' + duration = 0 + year = int(aired.split('/',-1)[2]) + img = video.find('a').find('img')['src'].encode('utf-8') + + url_video = URL_ROOT + video['about'].encode('utf-8') + + + info = { + 'video': { + 'title': title, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'mediatype': 'tvshow' + } + } + + # Nouveau pour ajouter le menu pour télécharger la vidéo + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url_video) + ')' + ) + context_menu.append(download_video) + # Fin + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url_video=url_video + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu # A ne pas oublier pour ajouter le bouton "Download" à chaque vidéo + }) + + # More videos... + videos.append({ + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( + action='channel_entry', + actualites_url=params.actualites_url, + actualites_name=params.actualites_name, + next='list_videos_actualites', + page=str(int(params.page) + 1), + update_listing=True, + previous_listing=str(videos) + ), + }) + + elif params.next == 'list_videos_emissions': + + # Cas emission (2 cas) (-0) ou (sans -0) + # 1ère page http://www.lcp.fr/emissions/evenements/replay-0 (url départ => http://www.lcp.fr/emissions/evenements-0) + # 1ère page http://www.lcp.fr/emissions/evenements/replay-0?page=1 + # ainsi de suite + # 1ère page : http://www.lcp.fr/emissions/en-voiture-citoyens/replay (url départ => http://www.lcp.fr/emissions/en-voiture-citoyens) + # 2ème page : http://www.lcp.fr/emissions/en-voiture-citoyens/replay?page=1 + # ainsi de suite + + if params.page == 0 and '-0' not in params.emission_url: + url = params.emission_url + '/replay' + elif params.page > 0 and '-0' not in params.emission_url: + url = params.emission_url + '/replay?page=' + str(params.page) + elif params.page == 0 and '-0' in params.emission_url: + url = params.emission_url[:-2] + '/replay-0' + elif params.page > 0 and '-0' in params.emission_url: + url = params.emission_url[:-2] + '/replay-0?page=' + str(params.page) + + file_path = utils.download_catalog( + url, + '%s_%s_%s.html' % ( + params.channel_name, + params.emission_name, + params.page)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + video_soup = root_soup.find_all('div', class_="node node-lcp-tv-episode node-teaser clearfix") + + for video in video_soup: + + title = video.find('h2').find('a').get_text().encode('utf-8') + ' - ' + video.find('h4').find('a').get_text().encode('utf-8') + value_date = video.find('div', class_="content").find('span', class_="date").get_text().encode('utf-8') + date = value_date.split(' ') + day = date[0] + try: + mounth = CORRECT_MOUNTH[date[1]] + except: + mounth = '00' + year = date[2] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + duration = 0 + duration = int(video.find('div', class_="content").find('div', class_="duration").find('div').find('span').get_text()) * 60 + img = video.find('a').find('img')['src'].encode('utf-8') + + url_video = URL_ROOT + video['about'].encode('utf-8') + + + info = { + 'video': { + 'title': title, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'mediatype': 'tvshow' + } + } + + # Nouveau pour ajouter le menu pour télécharger la vidéo + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url_video) + ')' + ) + context_menu.append(download_video) + # Fin + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url_video=url_video + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu # A ne pas oublier pour ajouter le bouton "Download" à chaque vidéo + }) + + # More videos... + videos.append({ + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( + action='channel_entry', + emission_url=params.emission_url, + emission_name=params.emission_name, + next='list_videos_emissions', + page=str(int(params.page) + 1), + update_listing=True, + previous_listing=str(videos) + ), + }) + + return common.PLUGIN.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_PLAYCOUNT, + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE + ), + content='tvshows', + update_listing='update_listing' in params, + ) + + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + html_live = utils.get_webcontent(URL_LIVE_SITE) + root_soup = bs(html_live, 'html.parser') + live_soup = root_soup.find( + 'iframe', + class_='embed-responsive-item') + + url_live_embeded = live_soup.get('src') + url_live = 'http:%s' % url_live_embeded + + title = '%s Live' % params.channel_name.upper() + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + + url = '' + + html_video = utils.get_webcontent(params.url_video) + url_video_embed = re.compile(r'<iframe src="(.*?)"').findall(html_video)[0] + + if 'dailymotion' in url_video_embed: + + url_video_embed_http = 'http:%s' % url_video_embed + if params.next == 'download_video': + return url_video_embed_http + html_video = utils.get_webcontent(url_video_embed_http) + html_video = html_video.replace('\\', '') + + all_url_video = re.compile(r'"type":"video/mp4","url":"(.*?)"').findall(html_video) + for datas in all_url_video: + url = datas + else: + # get videoId and accountId + videoId, accountId = re.compile(r'embed/(.*?)/(.*?)/').findall(url_video_embed)[0] + + html_json = utils.get_webcontent(URL_VIDEO_REPLAY % (videoId, accountId)) + + html_json_2 = re.compile(r'\((.*?)\);').findall(html_json)[0] + json_parser = json.loads(html_json_2) + + for playlist in json_parser['Playlist']: + datas_video = playlist['MediaFiles']['M3u8'] + for data in datas_video: + url = data['Url'] + + return url + + elif params.next == 'play_l': + + html_live = utils.get_webcontent(params.url) + html_live = html_live.replace('\\', '') + + url_live = re.compile(r'{"type":"application/x-mpegURL","url":"(.*?)"}]}').findall(html_live) + + # Just one flux no quality to choose + return url_live[0] + diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/lequipe.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/lequipe.py index 01ea101..3201586 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/lequipe.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/lequipe.py @@ -20,62 +20,105 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +import re +import ast from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -import re -import ast -auth = '?auth=1487366549-2688-mbe66p57-9b64a7bdc99718f9fc20facf756f8be9' +# TO DO +# Lot Code DailyMotion are present in some channel +# (create function to pass video_id from each channel using DailyMotion) +# Get Info Live -dailymotion_url = 'https://www.dailymotion.com/cdn/manifest/video/' +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() -url_root = 'https://www.lequipe.fr' +URL_ROOT = 'https://www.lequipe.fr' -categories = { - 'https://www.lequipe.fr/lachainelequipe/morevideos/0/': 'Tout', - 'https://www.lequipe.fr/lachainelequipe/morevideos/1/': 'L\'Équipe du soir', - 'https://www.lequipe.fr/lachainelequipe/morevideos/62/': 'L\'Équipe Type', - 'https://www.lequipe.fr/lachainelequipe/morevideos/88/': 'L\'Équipe Enquête', - 'https://www.lequipe.fr/lachainelequipe/morevideos/46/': 'Esprit Bleu' -} +URL_ROOT_VIDEO_LEQUIPE = 'https://www.lequipe.fr/lachainelequipe/' -correct_mounth = { - 'JANV.': '01', - 'FÉVR.': '02', - 'MARS.': '03', - 'AVRI': '04', - 'MAI': '05', - 'JUIN': '06', - 'JUIL.': '07', - 'AOÛT': '08', - 'SEPT.': '09', - 'OCTO.': '10', - 'NOVE.': '11', - 'DECE.': '12' -} +URL_REPLAY_VIDEO_LEQUIPE = 'https://www.lequipe.fr/lachainelequipe/morevideos/%s' +# Category_id +URL_DAILYMOTION_EMBED = 'http://www.dailymotion.com/embed/video/%s' +# Video_id def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: return get_video_url(params) else: return None +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build shows listing""" shows = [] - for category_url, category_name in categories.iteritems(): + # Get categories : + file_path = utils.download_catalog( + URL_ROOT_VIDEO_LEQUIPE, + '%s_video.html' % ( + params.channel_name)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + categories_soup = root_soup.find_all('a', class_="navtab__item js-tabs-item") + + for category in categories_soup: + + category_name = category.get_text().encode('utf-8') + category_url = URL_REPLAY_VIDEO_LEQUIPE % category.get('data-program-id') shows.append({ 'label': category_name, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', category_url=category_url, page='1', @@ -85,21 +128,22 @@ def list_shows(params): ) }) - return common.plugin.create_listing( + 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) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] if 'previous_listing' in params: videos = ast.literal_eval(params['previous_listing']) - url = params.category_url + params.page + url = params.category_url + '/' + params.page file_path = utils.download_catalog( url, '%s_%s_%s.html' % ( @@ -114,7 +158,12 @@ def list_videos(params): class_='colead') for program in category_soup: - url = program['href'].encode('utf-8') + + # Get Video_ID + url = URL_ROOT + program['href'].encode('utf-8') + html_video_equipe = utils.get_webcontent(url) + video_id = re.compile( + r'<iframe src="//www.dailymotion.com/embed/video/(.*?)\?', re.DOTALL).findall(html_video_equipe)[0] title = program.find( 'h2').get_text().encode('utf-8') @@ -124,42 +173,28 @@ def list_videos(params): img = colead__image.find( 'img')['data-src'].encode('utf-8') - views = colead__image.find( - 'span', - class_='colead__layerText--topright' - ).get_text().encode('utf-8') - - views = [int(s) for s in views.split() if s.isdigit()] - views = views[0] - date = colead__image.find( 'span', - class_='colead__layerText--bottomleft' - ).get_text().encode('utf-8') # 10 FÉVR. 2017 | 08:20 - date = date.split(' ') + class_='colead__layerText colead__layerText--bottomleft' + ).get_text().strip().encode('utf-8') # 07/09/17 | 01 min + date = date.split('/') day = date[0] - try: - mounth = correct_mounth[date[1]] - except: - mounth = '00' - year = date[2] + mounth = date[1] + year = '20' + date[2].split(' ')[0] date = '.'.join((day, mounth, year)) aired = '-'.join((year, mounth, day)) - # date : string (%d.%m.%Y / 01.01.2009) - # aired : string (2008-12-07) duration_string = colead__image.find( 'span', - class_='colead__layerText--bottomright' - ).get_text().encode('utf-8') - duration_list = duration_string.split(':') - duration = int(duration_list[0]) * 60 + int(duration_list[1]) + class_='colead__layerText colead__layerText--bottomleft' + ).get_text().strip().encode('utf-8') + duration_list = duration_string.split(' ') + duration = int(duration_list[2]) * 60 info = { 'video': { 'title': title, - 'playcount': views, 'aired': aired, 'date': date, 'duration': duration, @@ -168,22 +203,33 @@ def list_videos(params): } } + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + video_id=video_id) + ')' + ) + context_menu.append(download_video) + videos.append({ 'label': title, 'thumb': img, - 'url': common.plugin.get_url( + 'fanart': img, + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', - url=url + next='play_r', + video_id=video_id ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu }) # More videos... videos.append({ - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( action='channel_entry', category_url=params.category_url, category_name=params.category_name, @@ -194,7 +240,7 @@ def list_videos(params): ), }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -207,43 +253,91 @@ def list_videos(params): update_listing='update_listing' in params, ) +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + video_id = '' + url_live = '' + + html_live_equipe = utils.get_webcontent(URL_ROOT_VIDEO_LEQUIPE) + video_id = re.compile( + r'<iframe src="//www.dailymotion.com/embed/video/(.*?)\?', re.DOTALL).findall(html_live_equipe)[0] + + title = '%s Live' % params.channel_name.upper() + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } -@common.plugin.cached(common.cache_time) -def get_video_url(params): - url = url_root + params.url - html_video_equipe = utils.get_webcontent( - url) - - url_daily = re.compile( - r'<iframe src="//(.*?)"', re.DOTALL).findall(html_video_equipe)[0] - - url_daily = 'http://' + url_daily + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + video_id=video_id, + ), + 'is_playable': True, + 'info': info + }) - html_daily = utils.get_webcontent( - url_daily,) + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) - html_daily = html_daily.replace('\\', '') - urls_mp4 = re.compile( - r'{"type":"video/mp4","url":"(.*?)"}],"(.*?)":').findall(html_daily) - for url, quality in urls_mp4: - if quality == '480': - url_sd = url - elif quality == '720': - url_hd = url - elif quality == '1080': - url_hdplus = url - url_default = url +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + url_video = URL_DAILYMOTION_EMBED % params.video_id - desired_quality = common.plugin.get_setting( - params.channel_id + '.quality') + desired_quality = common.PLUGIN.get_setting('quality') - if desired_quality == 'HD+' and url_hdplus is not None: - return url_hdplus - elif desired_quality == 'HD' and url_hd is not None: - return url_hd - elif desired_quality == 'SD' and url_sd is not None: - return url_sd + if params.next == 'download_video': + return url_video else: - return url_default + html_video = utils.get_webcontent(url_video) + html_video = html_video.replace('\\', '') + + if params.next == 'play_l': + all_url_video = re.compile(r'{"type":"application/x-mpegURL","url":"(.*?)"').findall(html_video) + # Just One Quality + return all_url_video[0] + elif params.next == 'play_r': + all_url_video = re.compile(r'{"type":"video/mp4","url":"(.*?)"').findall(html_video) + if desired_quality == "DIALOG": + all_datas_videos = [] + for datas in all_url_video: + new_list_item = common.sp.xbmcgui.ListItem() + datas_quality = re.search('H264-(.+?)/', datas).group(1) + new_list_item.setLabel('H264-' + datas_quality) + new_list_item.setPath(datas) + all_datas_videos.append(new_list_item) + + seleted_item = common.sp.xbmcgui.Dialog().select("Choose Stream", all_datas_videos) + + return all_datas_videos[seleted_item].getPath().encode('utf-8') + elif desired_quality == 'BEST': + # Last video in the Best + for datas in all_url_video: + url = datas + return url + else: + return all_url_video[0] diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/nrj.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/nrj.py index e038c21..a313210 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/nrj.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/nrj.py @@ -20,263 +20,367 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +import json +import re +import xml.etree.ElementTree as ET +import requests +from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -from bs4 import BeautifulSoup as bs -url_replay = 'http://www.nrj-play.fr/%s/replay' +# TO DO +# Get Info Live +# Get CATEGORIES + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_ROOT = 'http://www.nrj-play.fr' + +URL_REPLAY = 'http://www.nrj-play.fr/%s/replay' # channel_name (nrj12, ...) -url_root = 'http://www.nrj-play.fr' +URL_COLLECTION_API = 'http://www.nrj-play.fr/%s/api/getreplaytvcollection' +# channel_name (nrj12, ...) + +URL_REPLAY_API = 'http://www.nrj-play.fr/%s/api/getreplaytvlist' +# channel_name (nrj12, ...) - HTTP 500 non stable + +URL_ALL_VIDEO = 'http://www.nrj-play.fr/sitemap-videos.xml' +# Meilleur stabilité mais perte des collections + +URL_GET_API_LIVE = 'http://www.nrj-play.fr/sitemap.xml' +# NOT_USED in this script (link api, live and more) +URL_COMPTE_LOGIN = 'https://www.nrj-play.fr/compte/login' +# TO DO add account for using Live Direct + +URL_LIVE_WITH_TOKEN = 'http://www.nrj-play.fr/compte/live?channel=%s' +# channel (nrj12, ...) - call this url after get session (url live with token inside this page) def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: return get_video_url(params) else: return None -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay with Categories + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Replay + modes.append({ + 'label' : 'Replay sans categorie', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_without_categories', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build shows listing""" shows = [] - if 'list_shows_1' in params.next: - # Build categories list (Tous les programmes, Séries, ...) - file_path = utils.download_catalog( - url_replay % params.channel_name, - '%s_replay.html' % params.channel_name, - ) - replay_html = open(file_path).read() - replay_soup = bs(replay_html, 'html.parser') + if 'list_shows_without_categories' in params.next: - categories_soup = replay_soup.find_all( - 'li', - class_='subNav-menu-item') + # Pour avoir toutes les videos + state_video = 'Toutes les videos (sans les categories)' - for category in categories_soup: - url_category = category.find('a')['href'].encode('utf-8') - title_category = category.find('a').get_text().encode('utf-8') + shows.append({ + 'label': state_video, + 'url': common.PLUGIN.get_url( + action='channel_entry', + state_video=state_video, + next='list_videos_1', + #title_category=category_name, + window_title=state_video + ) + }) - shows.append({ - 'label': title_category, - 'url': common.plugin.get_url( - action='channel_entry', - url_category=url_category, - next='list_shows_programs', - title_category=title_category, - window_title=title_category - ) - }) + else: + unique_item = dict() - elif 'list_shows_programs' in params.next: - # Build category's programs list - # (Crimes, tellement vrai, Le mad mag, ...) file_path = utils.download_catalog( - url_root + params.url_category, - '%s_%s_category.html' % ( - params.channel_name, - params.title_category), + URL_COLLECTION_API % params.channel_name, + '%s_collection.xml' % params.channel_name, ) - category_html = open(file_path).read() - category_soup = bs(category_html, 'html.parser') - - programs_soup = category_soup.find_all( - 'div', - class_='linkProgram') + collection_xml = open(file_path).read() - for program in programs_soup: - title = program.find( - 'h2', - class_='linkProgram-title').get_text().encode('utf-8') + xml_elements = ET.XML(collection_xml) - title = ' '.join(title.split()) + if 'list_shows_1' in params.next: + # Build categories list (Tous les programmes, Séries, ...) + collections = xml_elements.findall("collection") - url = program.find('a')['href'].encode('utf-8') - img = program.find('img')['src'].encode('utf-8') + # Pour avoir toutes les videos, certaines videos ont des + # categories non presentes dans cette URL 'url_collection_api' + state_video = 'Toutes les videos' shows.append({ - 'label': title, - 'thumb': img, - 'url': common.plugin.get_url( + 'label': state_video, + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_seasons', - url_program=url, - title_program=title, - window_title=title - ), + state_video=state_video, + next='list_videos_1', + #title_category=category_name, + window_title=state_video + ) }) - elif 'list_shows_seasons' in params.next: - file_path = utils.download_catalog( - url_root + params.url_program, - '%s_%s_program.html' % ( - params.channel_name, - params.title_program), - ) - program_html = open(file_path).read() - program_soup = bs(program_html, 'html.parser') - program_url = program_soup.find( - 'a', - class_='pushProgram-link')['href'].encode('utf-8') + for collection in collections: + + category_name = collection.findtext("category").encode('utf-8') + if category_name not in unique_item: + if category_name == '': + category_name = 'NO_CATEGORY' + unique_item[category_name] = category_name + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_name=category_name, + next='list_shows_programs', + #title_category=category_name, + window_title=category_name + ) + }) + + elif 'list_shows_programs' in params.next: + # Build programm list (Tous les programmes, Séries, ...) + collections = xml_elements.findall("collection") + + state_video = 'VIDEOS_BY_CATEGORY' + + for collection in collections: + if params.category_name == collection.findtext("category").encode('utf-8') \ + or (params.category_name == 'NO_CATEGORY' and \ + collection.findtext("category").encode('utf-8') == ''): + name_program = collection.findtext("name").encode('utf-8') + img_program = collection.findtext("picture") + id_program = collection.get("id") + + shows.append({ + 'label': name_program, + 'thumb': img_program, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_videos_1', + state_video=state_video, + id_program=id_program, + #title_program=name_program, + window_title=name_program + ) + }) + + return common.PLUGIN.create_listing( + shows, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_videos(params): + """Build videos listing""" + videos = [] + + if params.state_video == 'Toutes les videos (sans les categories)': file_path = utils.download_catalog( - url_root + program_url, - '%s_%s_program_fiche.html' % ( - params.channel_name, - params.title_program), + URL_ALL_VIDEO, + '%s_all_video.xml' % params.channel_name, ) - program_html = open(file_path).read() - program_soup = bs(program_html, 'html.parser') - - seasons_soup = program_soup.find( - 'ul', - class_='seasonsBox-list') - - if seasons_soup is not None: - for season in seasons_soup.find_all('li'): - title_season = season.find( - 'a').get_text().encode('utf-8') - season_url = season.find('a')['href'].encode('utf-8') - - shows.append({ - 'label': title_season, - 'url': common.plugin.get_url( + replay_xml = open(file_path).read() + + xml_elements = ET.XML(replay_xml) + + programs = xml_elements.findall("{http://www.sitemaps.org/schemas/sitemap/0.9}url") + + for program in programs: + + url_site = program.findtext( + "{http://www.sitemaps.org/schemas/sitemap/0.9}loc").encode('utf-8') + check_string = '%s/replay/' % params.channel_name + if url_site.count(check_string) > 0: + + # Title + title = url_site.rsplit('/', 1)[1].replace("-", " ").upper() + + video_node = program.findall( + "{http://www.google.com/schemas/sitemap-video/1.1}video")[0] + + # Duration + duration = 0 + + # Image + img = '' + img_node = video_node.find( + "{http://www.google.com/schemas/sitemap-video/1.1}thumbnail_loc") + img = img_node.text.encode('utf-8') + + # Url Video + url = '' + url_node = video_node.find( + "{http://www.google.com/schemas/sitemap-video/1.1}content_loc") + url = url_node.text.encode('utf-8') + + # Plot + plot = '' + plot_node = video_node.find( + "{http://www.google.com/schemas/sitemap-video/1.1}description") + if plot_node.text: + plot = plot_node.text.encode('utf-8') + + # Date + value_date = '' + value_date_node = video_node.find( + "{http://www.google.com/schemas/sitemap-video/1.1}publication_date") + value_date = value_date_node.text.encode('utf-8') + date = value_date.split('T')[0].split('-') + day = date[2] + mounth = date[1] + year = date[0] + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration, + 'aired': aired, + 'date': date, + 'year': year, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url_site) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_season_categories', - season_url=season_url, - title_program=params.title_program, - title_season=title_season, - window_title=title_season + next='play_r', + url_video=url ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu }) - else: - params['next'] = 'list_shows_season_categories' - params['season_url'] = program_url - params['title_program'] = params.title_program - params['title_season'] = 'no_season' - params['window_title'] = params.window_title - return list_shows(params) - - elif 'list_shows_season_categories': - # Build program's categories - # (Les vidéos, les actus, les bonus, ...) + else: file_path = utils.download_catalog( - url_root + params.season_url, - '%s_%s_%s_program_season.html' % ( - params.channel_name, - params.title_program, - params.title_season), + URL_REPLAY_API % params.channel_name, + '%s_replay.xml' % params.channel_name, ) - program_html = open(file_path).read() - program_soup = bs(program_html, 'html.parser') - - # We have to find all 'flag-category' tag and all title h2 - - season_categories = {} - flag_categories_soup = program_soup.find_all( - 'a', - attrs={'class': 'flag-category'}) - for flag_category in flag_categories_soup: - season_category_title = flag_category.get_text().encode('utf-8') - if season_category_title == '': - season_category_title = 'No name' - season_categories[season_category_title] = 'flag_category' - - titles_h2 = program_soup.find_all( - 'h2', - attrs={'class': 'title-2'}) - - for title_h2 in titles_h2: - if 'itemprop' not in title_h2.attrs: - separator = title_h2.parent.find( - 'div', - class_='separator-wrap') - if separator: - url = separator.find('a')['href'].encode('utf-8') - season_categories[title_h2.get_text().encode( - 'utf-8')] = url - - for season_category_title, \ - season_category_url in season_categories.iteritems(): - shows.append({ - 'label': season_category_title, - 'url': common.plugin.get_url( - action='channel_entry', - next='list_videos', - season_category_url=season_category_url, - season_url=params.season_url, - season_category_title=season_category_title, - page='1', - window_title=season_category_title - ), - }) + replay_xml = open(file_path).read() - return common.plugin.create_listing( - shows, - sort_methods=( - common.sp.xbmcplugin.SORT_METHOD_UNSORTED, - common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE - ), - ) + xml_elements = ET.XML(replay_xml) + programs = xml_elements.findall("program") -@common.plugin.cached(common.cache_time) -def list_videos(params): - videos = [] + for program in programs: + if params.state_video == 'Toutes les videos': + + # Title + title = program.findtext("title").encode('utf-8') + " - " + \ + program.findtext("subtitle").encode('utf-8') + + # Duration + duration = 0 + if program.findtext("duration"): + try: + duration = int(program.findtext("duration")) * 60 + except ValueError: + pass # or whatever + + # Image + img = program.find("photos").findtext("photo") + + # Url Video + url = '' #program.find("offres").find("offre").find("videos").findtext("video) + for i in program.find("offres").findall("offre"): + + date_value = i.get("startdate") + date_value_list = date_value.split(' ')[0].split('-') + day = date_value_list[2] + mounth = date_value_list[1] + year = date_value_list[0] - # flag_category case - if 'flag_category' in params.season_category_url: - program_html = utils.get_webcontent( - url_root + params.season_url - ) - program_soup = bs(program_html, 'html.parser') - - videos_soup = program_soup.find_all( - 'div', - attrs={'class': 'thumbnail', 'itemprop': 'video'}) - for video in videos_soup: - current_flag_category = video.find( - 'a', - attrs={'class': 'flag-category'}).get_text().encode('utf-8') - if current_flag_category == '': - current_flag_category = 'No name' - if current_flag_category and current_flag_category \ - == params.season_category_title: - - title_soup = video.find( - 'h3', - class_='thumbnail-title') - url = title_soup.find('a')['href'].encode('utf-8') - - title = title_soup.get_text().encode('utf-8') - title = ' '.join(title.split()) - - img = video.find('img')['src'].encode('utf-8') - try: - date = video.find('time').get_text() - date = date.encode('utf-8').split(' ')[1] - date_splited = date.split('/') - day = date_splited[0] - mounth = date_splited[1] - year = date_splited[2] - # date : string (%d.%m.%Y / 01.01.2009) - # aired : string (2008-12-07) date = '.'.join((day, mounth, year)) aired = '-'.join((year, mounth, day)) - except: - date = '' - aired = '' - year = '' + + for j in i.find("videos").findall("video"): + url = j.text.encode('utf-8') + + # Plot + plot = '' + for i in program.find("stories").findall("story"): + if int(i.get("maxlength")) == 680: + plot = i.text.encode('utf-8') info = { 'video': { 'title': title, + 'plot': plot, + 'duration': duration, 'aired': aired, 'date': date, 'year': year, @@ -284,109 +388,195 @@ def list_videos(params): } } + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url) + ')' + ) + context_menu.append(download_video) + videos.append({ 'label': title, + 'fanart': img, 'thumb': img, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', + next='play_r', url_video=url ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu }) - # others url case - else: - program_html = utils.get_webcontent( - url_root + params.season_category_url + '?page=' + params.page - ) - program_soup = bs(program_html, 'html.parser') - - videos_soup = program_soup.find_all( - 'div', - attrs={'class': 'item col-xs-6 col-md-4'}) - for video in videos_soup: - - title_soup = video.find( - 'h3', - class_='thumbnail-title') - url = title_soup.find('a')['href'].encode('utf-8') - - title = title_soup.get_text().encode('utf-8') - title = ' '.join(title.split()) - - img = video.find('img')['src'].encode('utf-8') - try: - date = video.find('time').get_text() - date = date.encode('utf-8').split(' ')[1] - except: - date = video.find('time').get_text().encode('utf-8') - - date_splited = date.split('/') - day = date_splited[0] - mounth = date_splited[1] - year = date_splited[2] - - date = '.'.join((day, mounth, year)) - aired = '-'.join((year, mounth, day)) - # date : string (%d.%m.%Y / 01.01.2009) - # aired : string (2008-12-07) - info = { - 'video': { - 'title': title, - 'aired': aired, - 'date': date, - 'year': year, - 'mediatype': 'tvshow' - } - } - videos.append({ - 'label': title, - 'thumb': img, - 'url': common.plugin.get_url( - action='channel_entry', - next='play', - url_video=url - ), - 'is_playable': True, - 'info': info - }) + elif params.id_program == program.get("IDSERIE"): - # More videos... - videos.append({ - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( - action='channel_entry', - next='list_videos', - season_category_url=params.season_category_url, - season_url=params.season_url, - season_category_title=params.season_category_title, - page=str(int(params.page) + 1), - window_title=params.window_title - ) + # Title + title = program.findtext("title").encode('utf-8') + " - " + \ + program.findtext("subtitle").encode('utf-8') - }) + # Duration + duration = 0 + if program.findtext("duration"): + try: + duration = int(program.findtext("duration")) * 60 + except ValueError: + pass # or whatever + + # Image + img = program.find("photos").findtext("photo") + + # Url Video + url = '' #program.find("offres").find("offre").find("videos").findtext("video) + for i in program.find("offres").findall("offre"): + + date_value = i.get("startdate") + date_value_list = date_value.split(' ')[0].split('-') + day = date_value_list[2] + mounth = date_value_list[1] + year = date_value_list[0] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) - return common.plugin.create_listing( + for j in i.find("videos").findall("video"): + url = j.text.encode('utf-8') + + # Plot + plot = '' + for i in program.find("stories").findall("story"): + if int(i.get("maxlength")) == 680: + plot = i.text.encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration, + 'aired': aired, + 'date': date, + 'year': year, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url_video=url + ), + 'is_playable': True, + 'info': info + # 'context_menu': context_menu + }) + + 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 + 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 list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + session_requests = requests.session() + result = session_requests.get(URL_COMPTE_LOGIN) + + token_form_login = re.compile( + r'name=\"login_form\[_token\]\" value=\"(.*?)\"').findall(result.text)[0] + + # Build PAYLOAD + payload = { + "login_form[email]": common.PLUGIN.get_setting( + params.channel_id.rsplit('.', 1)[0] + '.login'), + "login_form[password]": common.PLUGIN.get_setting( + params.channel_id.rsplit('.', 1)[0] + '.password'), + "login_form[_token]": token_form_login + } + + # LOGIN + result_2 = session_requests.post( + URL_COMPTE_LOGIN, data = payload, headers = dict(referer = URL_COMPTE_LOGIN)) + + # GET page with url_live with the session logged + result_3 = session_requests.get( + URL_LIVE_WITH_TOKEN % (params.channel_name), + headers=dict( + referer=URL_LIVE_WITH_TOKEN % (params.channel_name))) + + root_soup = bs(result_3.text, 'html.parser') + live_soup = root_soup.find('div', class_="player") + + url_live_json = live_soup.get('data-options') + url_live_json_jsonparser = json.loads(url_live_json) + + url_live = url_live_json_jsonparser["file"] + + title = '%s Live' % params.channel_name.upper() + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url_live=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def get_video_url(params): - if url_root in params.url_video: - url_video = params.url_video - else: - url_video = url_root + params.url_video - video_html = utils.get_webcontent( - url_video) - video_soup = bs(video_html, 'html.parser') - return video_soup.find( - 'meta', - attrs={'itemprop': 'contentUrl'})['content'].encode('utf-8') + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + # Just One format of each video (no need of QUALITY) + return params.url_video + elif params.next == 'play_l': + return params.url_live diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/numero23.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/numero23.py index 8f20db7..1beab9d 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/numero23.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/numero23.py @@ -20,38 +20,101 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +import re +import json from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -import ast -import re -url_root = 'http://www.numero23.fr/replay/' +# TO DO +# Get more info Live TV (picture, plot) +# Get year from Replay + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_REPLAY = 'http://www.numero23.fr/replay/' +URL_INFO_LIVE_JSON = 'http://www.numero23.fr/wp-content/cache/n23-direct.json' +# Title, DailyMotion Id (Video) + +URL_DAILYMOTION_EMBED = 'http://www.dailymotion.com/embed/video/%s' +# Video_id def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: return get_video_url(params) else: return None +CORRECT_MONTH = { + 'janvier' : '01', + 'février' : '02', + 'mars' : '03', + 'avril' : '04', + 'mai' : '05', + 'juin' : '06', + 'juillet' : '07', + 'août' : '08', + 'septembre' : '09', + 'octobre' : '10', + 'novembre' : '11', + 'décembre' : '12' +} + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build shows listing""" shows = [] - if 'previous_listing' in params: - shows = ast.literal_eval(params['previous_listing']) - unique_item = {} - if 'unique_item' in params: - unique_item = ast.literal_eval(params['unique_item']) - if params.next == 'list_shows_1': file_path = utils.download_catalog( - url_root, + URL_REPLAY, params.channel_name + '.html') root_html = open(file_path).read() root_soup = bs(root_html, 'html.parser') @@ -62,127 +125,130 @@ def list_shows(params): ) for category in categories_soup.find_all('a'): - category_name = category.find('span').get_text().encode('utf-8') - category_url = category['href'].encode('utf-8') + category_name = category.find('span').get_text().encode('utf-8').replace( + '\n', ' ').replace('\r', ' ').rstrip('\r\n') + category_hash = common.sp.md5(category_name).hexdigest() + + url = category.get('href').encode('utf-8') shows.append({ 'label': category_name, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - category_url=category_url, - next='list_shows_cat', + category_hash=category_hash, + next='list_videos_cat', + url=url, window_title=category_name, category_name=category_name, - page='1' ) }) - elif params.next == 'list_shows_cat': - url_splited = params.category_url.split('?') - url_category = url_splited[0] + 'page/' + \ - params.page + '/?' + url_splited[1] - file_path = utils.download_catalog( - url_category, - '%s_%s.html' % (params.channel_name, params.category_name) - ) - category_html = open(file_path).read() - category_soup = bs(category_html, 'html.parser') - - programs_soup = category_soup.find( - 'div', - class_='videos replay' - ) - for program in programs_soup.find_all('div', class_='program'): - program_name_url = program.find('h3').find('a') - program_name = program_name_url.get_text().encode('utf-8') - if program_name not in unique_item: - unique_item[program_name] = program_name - program_url = program_name_url['href'].encode('utf-8') - program_img = program.find('img')['src'].encode('utf-8') - - shows.append({ - 'label': program_name, - 'thumb': program_img, - 'url': common.plugin.get_url( - action='channel_entry', - program_url=program_url, - next='list_videos', - window_title=program_name, - program_name=program_name - ) - }) - - # More videos... - shows.append({ - 'label': common.addon.get_localized_string(30108), - 'url': common.plugin.get_url( - action='channel_entry', - next='list_shows_cat', - page=str(int(params.page) + 1), - window_title=params.window_title, - update_listing=True, - unique_item=str(unique_item), - category_url=params.category_url, - category_name=params.category_name, - previous_listing=str(shows) - - ) - }) - - return common.plugin.create_listing( + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, common.sp.xbmcplugin.SORT_METHOD_LABEL ), - update_listing='update_listing' in params, ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] + paged = 1 + url_replay_paged = params.url + '&paged=' + str(paged) + file_path = utils.download_catalog( - params.program_url, - '%s_%s.html' % (params.channel_name, params.program_name) + url_replay_paged, + '%s_%s_%s.html' % (params.channel_name, params.category_name, str(paged)) ) program_html = open(file_path).read() program_soup = bs(program_html, 'html.parser') - videos_soup = program_soup.find_all('div', class_='box program') + videos_soup = program_soup.find_all('div', class_='program sticky video') + + while len(videos_soup) != 0: + for video in videos_soup: + + info_video = video.find_all('p') + + video_title = video.find('h3').find('a').get_text().encode('utf-8').replace( + '\n', ' ').replace('\r', ' ').rstrip('\r\n') + ' - ' + video.find( + 'p', class_="red").get_text().encode( + 'utf-8').replace('\n', ' ').replace('\r', ' ').rstrip('\r\n') + video_img = video.find('img')['src'].encode('utf-8') + video_id = video.find('div', class_="player")['data-id-video'].encode('utf-8') + video_duration = 0 + video_duration_list = str(info_video[3]).replace( + "<p><strong>", '').replace("</strong></p>", '').split(':') + if len(video_duration_list) > 2: + video_duration = int(video_duration_list[0]) * 3600 + int(video_duration_list[1]) \ + * 60 + int(video_duration_list[2]) + else: + video_duration = int(video_duration_list[0]) * 60 + int(video_duration_list[1]) + + # get month and day on the page + date_list = str(info_video[2]).replace("<p>", '').replace("</p>", '').split(' ') + day = date_list[2] + try: + mounth = CORRECT_MONTH[date_list[3]] + except: + mounth = '00' + # get year ? + year = '2017' + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + info = { + 'video': { + 'title': video_title, + 'aired': aired, + 'date': date, + 'duration': video_duration, + 'year': year, + 'mediatype': 'tvshow' + } + } - if len(videos_soup) == 0: - videos_soup = program_soup.find_all( - 'div', class_='program sticky video') + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + video_id=video_id) + ')' + ) + context_menu.append(download_video) - for video in videos_soup: - video_title = video.find( - 'p').get_text().encode('utf-8').replace( - '\n', ' ').replace('\r', ' ').rstrip('\r\n') - video_img = video.find('img')['src'].encode('utf-8') - video_url = video.find('a')['href'].encode('utf-8') + videos.append({ + 'label': video_title, + 'thumb': video_img, + 'fanart': video_img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + video_id=video_id + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + paged = paged + 1 - info = { - 'video': { - 'title': video_title, - 'mediatype': 'tvshow' - } - } + url_replay_paged = params.url + '&paged=' + str(paged) + + file_path = utils.download_catalog( + url_replay_paged, + '%s_%s_%s.html' % (params.channel_name, params.category_name, str(paged)) + ) + program_html = open(file_path).read() + program_soup = bs(program_html, 'html.parser') - videos.append({ - 'label': video_title, - 'thumb': video_img, - 'url': common.plugin.get_url( - action='channel_entry', - next='play', - video_url=video_url - ), - 'is_playable': True, - 'info': info - }) - - return common.plugin.create_listing( + videos_soup = program_soup.find_all('div', class_='program sticky video') + + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -190,45 +256,95 @@ def list_videos(params): ), content='tvshows') +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] -@common.plugin.cached(common.cache_time) -def get_video_url(params): - video_html = utils.get_webcontent( - params.video_url + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + file_path = utils.download_catalog( + URL_INFO_LIVE_JSON, + '%s_info_live.json' % (params.channel_name) ) - video_soup = bs(video_html, 'html.parser') - video_id = video_soup.find( - 'div', class_='video')['data-video-id'].encode('utf-8') - - url_daily = 'http://www.dailymotion.com/embed/video/' + video_id - - html_daily = utils.get_webcontent( - url_daily,) - - html_daily = html_daily.replace('\\', '') - - urls_mp4 = re.compile( - r'{"type":"video/mp4","url":"(.*?)"}],"(.*?)"').findall(html_daily) - - for url, quality in urls_mp4: - if quality == '480': - url_sd = url - elif quality == '720': - url_hd = url - elif quality == '1080': - url_hdplus = url - else: - continue - url_default = url - - desired_quality = common.plugin.get_setting( - params.channel_id + '.quality') - - if desired_quality == 'HD+' and url_hdplus is not None: - return url_hdplus - elif desired_quality == 'HD' and url_hd is not None: - return url_hd - elif desired_quality == 'SD' and url_sd is not None: - return url_sd + file_info_live = open(file_path).read() + json_parser = json.loads(file_info_live) + + title = json_parser["titre"].encode('utf-8') + + video_id = json_parser["video"].encode('utf-8') + + #url_live = url_dailymotion_embed % video_id + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + video_id=video_id, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + url_video = URL_DAILYMOTION_EMBED % params.video_id + + desired_quality = common.PLUGIN.get_setting('quality') + + if params.next == 'download_video': + return url_video else: - return url_default + html_video = utils.get_webcontent(url_video) + html_video = html_video.replace('\\', '') + + if params.next == 'play_l': + all_url_video = re.compile( + r'{"type":"application/x-mpegURL","url":"(.*?)"').findall(html_video) + # Just One Quality + return all_url_video[0] + elif params.next == 'play_r': + all_url_video = re.compile(r'{"type":"video/mp4","url":"(.*?)"').findall(html_video) + if desired_quality == "DIALOG": + all_datas_videos = [] + for datas in all_url_video: + new_list_item = common.sp.xbmcgui.ListItem() + datas_quality = re.search('H264-(.+?)/', datas).group(1) + new_list_item.setLabel('H264-' + datas_quality) + new_list_item.setPath(datas) + all_datas_videos.append(new_list_item) + + seleted_item = common.sp.xbmcgui.Dialog().select("Choose Stream", all_datas_videos) + + return all_datas_videos[seleted_item].getPath().encode('utf-8') + elif desired_quality == 'BEST': + #Last video in the Best + for datas in all_url_video: + url = datas + return url + else: + return all_url_video[0] diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py index a64d7d0..156edd2 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/pluzz.py @@ -21,36 +21,51 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +# TO DO # Liste A à Z # Si FR3 ou FR1 : Régions - import json +import ast from resources.lib import utils from resources.lib import common -import ast -channel_catalog = 'http://pluzz.webservices.francetelevisions.fr/' \ + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +CHANNEL_CATALOG = 'http://pluzz.webservices.francetelevisions.fr/' \ 'pluzz/liste/type/replay/nb/10000/chaine/%s' -# channel_catalog = 'https://pluzz.webservices.francetelevisions.fr/' \ + +CHANNEL_LIVE = 'http://pluzz.webservices.francetelevisions.fr/' \ + 'pluzz/liste/type/live/nb/10000/chaine/%s' + +# CHANNEL_CATALOG = 'https://pluzz.webservices.francetelevisions.fr/' \ # 'mobile/liste/type/replay/chaine/%s/nb/20/debut/%s' # page inc: 20 -show_info = 'http://webservices.francetelevisions.fr/tools/' \ +SHOW_INFO = 'http://webservices.francetelevisions.fr/tools/' \ 'getInfosOeuvre/v2/?idDiffusion=%s&catalogue=Pluzz' -url_img = 'http://refonte.webservices.francetelevisions.fr%s' +LIVE_INFO = 'http://webservices.francetelevisions.fr/tools/' \ + 'getInfosOeuvre/v2/?idDiffusion=SIM_%s' + +HDFAUTH_URL = 'http://hdfauth.francetv.fr/esi/TA?format=json&url=%s' + +URL_IMG = 'http://refonte.webservices.francetelevisions.fr%s' -url_search = 'https://pluzz.webservices.francetelevisions.fr/' \ +URL_SEARCH = 'https://pluzz.webservices.francetelevisions.fr/' \ 'mobile/recherche/nb/20/tri/date/requete/%s/debut/%s' -url_alpha = 'https://pluzz.webservices.francetelevisions.fr/' \ +URL_ALPHA = 'https://pluzz.webservices.francetelevisions.fr/' \ 'mobile/liste/type/replay/tri/alpha/sens/%s/nb/100/' \ 'debut/%s/lastof/1' # sens: asc or desc # page inc: 100 -categories_display = { +CATEGORIES_DISPLAY = { "france2": "France 2", "france3": "France 3", "france4": "France 4", @@ -76,58 +91,103 @@ categories_display = { "culture": "Culture" } -categories = { +CATEGORIES = { 'Toutes catégories': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/chaine/%s/nb/20/debut/%s', + 'mobile/liste/type/replay/chaine/%s/nb/20/debut/%s', 'Info': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/info/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/info/nb/20/debut/%s', 'Documentaire': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/documentaire/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/documentaire/nb/20/debut/%s', 'Série & Fiction': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/seriefiction/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/seriefiction/nb/20/debut/%s', 'Magazine': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/magazine/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/magazine/nb/20/debut/%s', 'Culture': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/culture/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/culture/nb/20/debut/%s', 'Jeunesse': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/jeunesse/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/jeunesse/nb/20/debut/%s', 'Divertissement': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/divertissement/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/divertissement/nb/20/debut/%s', 'Sport': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/sport/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/sport/nb/20/debut/%s', 'Jeu': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/rubrique/jeu/nb/20/debut/%s', + 'mobile/liste/type/replay/rubrique/jeu/nb/20/debut/%s', 'Version multilingue (VM)': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/filtre/multilingue/type/replay/nb/20/debut/%s', + 'mobile/liste/filtre/multilingue/type/replay/nb/20/debut/%s', 'Sous-titrés': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/filtre/soustitrage/type/replay/nb/20/debut/%s', + 'mobile/liste/filtre/soustitrage/type/replay/nb/20/debut/%s', 'Audiodescription (AD)': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/filtre/audiodescription/type/replay/nb/20/debut/%s', + 'mobile/liste/filtre/audiodescription/type/replay/nb/20/debut/%s', 'Tous publics': 'https://pluzz.webservices.francetelevisions.fr/' - 'mobile/liste/type/replay/filtre/touspublics/nb/20/debut/%s' + 'mobile/liste/type/replay/filtre/touspublics/nb/20/debut/%s' } def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: - return get_video_URL(params) + return get_video_url(params) elif 'search' in params.next: return search(params) + return None -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def change_to_nicer_name(original_name): - if original_name in categories_display: - return categories_display[original_name] + """Convert id name to label name""" + if original_name in CATEGORIES_DISPLAY: + return CATEGORIES_DISPLAY[original_name] return original_name -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + if params.channel_name != 'franceinfo': + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + if params.channel_name != 'la_1ere': + modes.append({ + 'label' : _('Live TV'), + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build categories listing""" shows = [] if 'previous_listing' in params: shows = ast.literal_eval(params['previous_listing']) @@ -148,7 +208,8 @@ def list_shows(params): # Level 0 if params.next == 'list_shows_1': - url_json = channel_catalog % (real_channel) + + url_json = CHANNEL_CATALOG % (real_channel) file_path = utils.download_catalog( url_json, '%s.json' % ( @@ -164,7 +225,7 @@ def list_shows(params): shows.append({ 'label': rubrique_title, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', rubrique=rubrique, next='list_shows_2_cat', @@ -174,57 +235,57 @@ def list_shows(params): # Last videos shows.append({ - 'label': common.addon.get_localized_string(30104), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30104), + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_shows_last', page='0', - window_title=common.addon.get_localized_string(30104) + window_title=common.ADDON.get_localized_string(30104) ) }) # Search shows.append({ - 'label': common.addon.get_localized_string(30103), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30103), + 'url': common.PLUGIN.get_url( action='channel_entry', next='search', page='0', - window_title=common.addon.get_localized_string(30103) + window_title=common.ADDON.get_localized_string(30103) ) }) # from A to Z shows.append({ - 'label': common.addon.get_localized_string(30105), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30105), + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_shows_from_a_to_z', - window_title=common.addon.get_localized_string(30105) + window_title=common.ADDON.get_localized_string(30105) ) }) # level 1 elif 'list_shows_from_a_to_z' in params.next: shows.append({ - 'label': common.addon.get_localized_string(30106), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30106), + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_2_from_a_to_z_categories', + next='list_shows_2_from_a_to_z_CATEGORIES', page='0', - url=url_alpha % ('asc', '%s'), + url=URL_ALPHA % ('asc', '%s'), sens='asc', rubrique='no_rubrique', window_title=params.window_title ) }) shows.append({ - 'label': common.addon.get_localized_string(30107), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30107), + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_2_from_a_to_z_categories', + next='list_shows_2_from_a_to_z_CATEGORIES', page='0', - url=url_alpha % ('desc', '%s'), + url=URL_ALPHA % ('desc', '%s'), sens='desc', rubrique='no_rubrique', window_title=params.window_title @@ -233,12 +294,12 @@ def list_shows(params): # level 1 elif 'list_shows_last' in params.next: - for title, url in categories.iteritems(): + for title, url in CATEGORIES.iteritems(): if 'Toutes catégories' in title: url = url % (params.channel_name, '%s') shows.append({ 'label': title, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos_last', page='0', @@ -251,13 +312,13 @@ def list_shows(params): # level 1 or 2 elif 'list_shows_2' in params.next: if 'list_shows_2_cat' in params.next: - url_json = channel_catalog % (real_channel) + url_json = CHANNEL_CATALOG % (real_channel) file_path = utils.download_catalog( url_json, '%s.json' % ( params.channel_name)) - elif 'list_shows_2_from_a_to_z_categories' in params.next: - url_json = url_alpha % (params.sens, params.page) + elif 'list_shows_2_from_a_to_z_CATEGORIES' in params.next: + url_json = URL_ALPHA % (params.sens, params.page) file_path = utils.download_catalog( url_json, '%s_%s_%s_alpha.json' % ( @@ -281,7 +342,7 @@ def list_shows(params): id_programme = emission['id_emission'].encode('utf-8') if id_programme not in unique_item: unique_item[id_programme] = id_programme - icon = url_img % (emission['image_large']) + icon = URL_IMG % (emission['image_large']) genre = emission['genre'] accroche_programme = emission['accroche_programme'] @@ -296,7 +357,7 @@ def list_shows(params): 'label': titre_programme, 'thumb': icon, 'fanart': icon, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos_1', id_programme=id_programme, @@ -307,13 +368,13 @@ def list_shows(params): ), 'info': info }) - if params.next == 'list_shows_2_from_a_to_z_categories': + if params.next == 'list_shows_2_from_a_to_z_CATEGORIES': # More videos... shows.append({ - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( action='channel_entry', - next='list_shows_2_from_a_to_z_categories', + next='list_shows_2_from_a_to_z_CATEGORIES', sens=params.sens, page=str(int(params.page) + 100), window_title=params.window_title, @@ -323,7 +384,7 @@ def list_shows(params): ) }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -333,15 +394,16 @@ def list_shows(params): ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] if 'previous_listing' in params: videos = ast.literal_eval(params['previous_listing']) if 'search' in params.next: file_path = utils.download_catalog( - url_search % (params.query, params.page), + URL_SEARCH % (params.query, params.page), '%s_%s_search.json' % (params.channel_name, params.query), force_dl=True ) @@ -366,7 +428,7 @@ def list_videos(params): else: file_path = utils.download_catalog( - channel_catalog % params.channel_name, + CHANNEL_CATALOG % params.channel_name, '%s.json' % params.channel_name ) file_prgm = open(file_path).read() @@ -398,40 +460,40 @@ def list_videos(params): continue file_prgm = utils.get_webcontent( - show_info % (emission['id_diffusion'])) + SHOW_INFO % (emission['id_diffusion'])) if(file_prgm != ''): - json_parserShow = json.loads(file_prgm) - if json_parserShow['synopsis']: - plot = json_parserShow['synopsis'].encode('utf-8') - if json_parserShow['diffusion']['date_debut']: - date = json_parserShow['diffusion']['date_debut'] + json_parser_show = json.loads(file_prgm) + if json_parser_show['synopsis']: + plot = json_parser_show['synopsis'].encode('utf-8') + if json_parser_show['diffusion']['date_debut']: + date = json_parser_show['diffusion']['date_debut'] date = date.encode('utf-8') - if json_parserShow['real_duration']: - duration = int(json_parserShow['real_duration']) - if json_parserShow['titre']: - title = json_parserShow['titre'].encode('utf-8') - if json_parserShow['sous_titre']: + if json_parser_show['real_duration']: + duration = int(json_parser_show['real_duration']) + if json_parser_show['titre']: + title = json_parser_show['titre'].encode('utf-8') + if json_parser_show['sous_titre']: title = ' '.join(( title, '- [I]', - json_parserShow['sous_titre'].encode('utf-8'), + json_parser_show['sous_titre'].encode('utf-8'), '[/I]')) - if json_parserShow['genre'] != '': + if json_parser_show['genre'] != '': genre = \ - json_parserShow['genre'].encode('utf-8') + json_parser_show['genre'].encode('utf-8') episode = 0 - if 'episode' in json_parserShow: - episode = json_parserShow['episode'] + if 'episode' in json_parser_show: + episode = json_parser_show['episode'] season = 0 - if 'saison' in json_parserShow: - season = json_parserShow['saison'] + if 'saison' in json_parser_show: + season = json_parser_show['saison'] cast = [] director = '' - personnes = json_parserShow['personnes'] + personnes = json_parser_show['personnes'] for personne in personnes: fonctions = ' '.join( x.encode('utf-8') for x in personne['fonctions']) @@ -452,8 +514,8 @@ def list_videos(params): # date : string (%d.%m.%Y / 01.01.2009) # aired : string (2008-12-07) - # image = url_img % (json_parserShow['image']) - image = json_parserShow['image_secure'] + # image = URL_IMG % (json_parserShow['image']) + image = json_parser_show['image_secure'] info = { 'video': { @@ -472,24 +534,36 @@ def list_videos(params): } } + # Nouveau pour ajouter le menu pour télécharger la vidéo + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + id_diffusion=id_diffusion) + ')' + ) + context_menu.append(download_video) + # Fin + videos.append({ 'label': title, 'fanart': image, 'thumb': image, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', + next='play_r', id_diffusion=id_diffusion ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu # A ne pas oublier pour ajouter le bouton "Download" à chaque vidéo }) if 'search' in params.next: # More videos... videos.append({ - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( action='channel_entry', next='list_videos_search', query=params.query, @@ -504,8 +578,8 @@ def list_videos(params): elif 'last' in params.next: # More videos... videos.append({ - 'label': common.addon.get_localized_string(30100), - 'url': common.plugin.get_url( + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( action='channel_entry', url=params.url, next=params.next, @@ -518,7 +592,7 @@ def list_videos(params): }) - return common.plugin.create_listing( + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -532,29 +606,202 @@ def list_videos(params): update_listing='update_listing' in params, ) +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] -@common.plugin.cached(common.cache_time) -def get_video_URL(params): - file_prgm = utils.get_webcontent(show_info % (params.id_diffusion)) + real_channel = params.channel_name + + title = '' + plot = '' + duration = 0 + date = '' + genre = '' + + if real_channel != 'franceinfo': + url_json_live = CHANNEL_LIVE % (real_channel) + file_path_live = utils.download_catalog( + url_json_live, + 'live_%s.json' % ( + params.channel_name)) + file_prgm_live = open(file_path_live).read() + json_parser_live = json.loads(file_prgm_live) + emissions_live = json_parser_live['reponse']['emissions'] + + for emission in emissions_live: + id_programme = emission['id_programme'].encode('utf-8') + if id_programme == '': + id_programme = emission['id_emission'].encode('utf-8') + id_diffusion = emission['id_diffusion'] + chaine_id = emission['chaine_id'].encode('utf-8') + + start_time_emission = 'Début : ' + emission['date_diffusion'].split('T')[1].encode('utf-8') + + if emission['accroche']: + plot = start_time_emission + '\n ' + emission['accroche'].encode('utf-8') + elif emission['accroche_programme']: + plot = start_time_emission + '\n ' + emission['accroche_programme'].encode('utf-8') + if emission['date_diffusion']: + date = emission['date_diffusion'] + date = date.encode('utf-8') + if emission['duree']: + duration = int(emission['duree']) * 60 + if emission['titre']: + title = emission['titre'].encode('utf-8') + + if emission['genre'] != '': + genre = \ + emission['genre'].encode('utf-8') + + episode = 0 + if 'episode' in emission: + episode = emission['episode'] + + season = 0 + if 'saison' in emission: + season = emission['saison'] + + cast = [] + director = '' + if emission['realisateurs'] in emission: + director = emission['realisateurs'].encode('utf-8') + if emission['acteurs'] in emission: + cast.append(emission['acteurs'].encode('utf-8')) + + year = int(date[:4]) + month = int(date[5:7]) + day = int(date[8:10]) + aired = '-'.join((str(year), str(month), str(day))) + + + image = URL_IMG % (emission['image_large']) + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'aired': aired, + 'date': date, + 'duration': duration, + #year': year, + 'genre': genre, + 'mediatype': 'tvshow', + 'season': season, + 'episode': episode, + 'cast': cast, + 'director': director + } + } + + lives.append({ + 'label': title, + 'fanart': image, + 'thumb': image, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + id_diffusion=id_diffusion + ), + 'is_playable': True, + 'info': info + }) + else: + + title = '%s Live' % params.channel_name + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'date': date, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_l' + ), + 'is_playable': True, + 'info': info + }) + + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + + if params.next == 'play_r' or params.next == 'download_video': + file_prgm = utils.get_webcontent(SHOW_INFO % (params.id_diffusion)) json_parser = json.loads(file_prgm) - url_HD = '' - url_SD = '' + + desired_quality = common.PLUGIN.get_setting('quality') + + url_selected = '' + + if desired_quality == "DIALOG": + all_datas_videos = [] + + for video in json_parser['videos']: + if video['format'] == 'hls_v5_os' or video['format'] == 'm3u8-download': + new_list_item = common.sp.xbmcgui.ListItem() + if video['format'] == 'hls_v5_os': + new_list_item.setLabel("HD") + else: + new_list_item.setLabel("SD") + new_list_item.setPath(video['url']) + all_datas_videos.append(new_list_item) + + seleted_item = common.sp.xbmcgui.Dialog().select( + _('Choose video quality'), + all_datas_videos) + + if seleted_item == -1: + return None + + url_selected = all_datas_videos[seleted_item].getPath() + + elif desired_quality == "BEST": + for video in json_parser['videos']: + if video['format'] == 'hls_v5_os': + url_selected = video['url'] + else: + for video in json_parser['videos']: + if video['format'] == 'm3u8-download': + url_selected = video['url'] + + return url_selected + + elif params.next == 'play_l': + + file_prgm = utils.get_webcontent(LIVE_INFO % (params.channel_name)) + json_parser = json.loads(file_prgm) + + url_selected = '' + for video in json_parser['videos']: if video['format'] == 'hls_v5_os': - url_HD = video['url'] - if video['format'] == 'm3u8-download': - url_SD = video['url'] + url_protected = video['url'] - desired_quality = common.plugin.get_setting( - params.channel_id + '.quality') + file_prgm2 = utils.get_webcontent(HDFAUTH_URL % (url_protected)) + json_parser2 = json.loads(file_prgm2) - if desired_quality == 'HD' and url_HD is not None: - return url_HD - else: - return url_SD + return json_parser2['url'] def search(params): + """Show keyboard to search a program""" keyboard = common.sp.xbmc.Keyboard( default='', title='', diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/publicsenat.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/publicsenat.py new file mode 100755 index 0000000..33d18d6 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/publicsenat.py @@ -0,0 +1,444 @@ +# -*- 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 re +import ast +from bs4 import BeautifulSoup as bs +from resources.lib import utils +from resources.lib import common + +# TO DO +# Add info LIVE TV + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_ROOT = 'https://www.publicsenat.fr' + +URL_LIVE_SITE = 'https://www.publicsenat.fr/direct' + +URL_DAILYMOTION_EMBED = 'http://www.dailymotion.com/embed/video/%s' + +def channel_entry(params): + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: + return list_shows(params) + elif 'list_videos' in params.next: + return list_videos(params) + elif 'live' in params.next: + return list_live(params) + elif 'play' in params.next: + return get_video_url(params) + +CATEGORIES = { + 'https://www.publicsenat.fr/recherche/type/episode/' \ + 'field_theme/politique-4127?sort_by=pse_search_date_publication' : 'Politique', + 'https://www.publicsenat.fr/recherche/type/episode/' \ + 'field_theme/societe-4126?sort_by=pse_search_date_publication' : 'Société', + 'https://www.publicsenat.fr/recherche/type/episode/' \ + 'field_theme/debat-4128?sort_by=pse_search_date_publication' : 'Débat' +} + +CORRECT_MONTH = { + 'janvier' : '01', + 'février' : '02', + 'mars' : '03', + 'avril' : '04', + 'mai' : '05', + 'juin' : '06', + 'juillet' : '07', + 'août' : '08', + 'septembre' : '09', + 'octobre' : '10', + 'novembre' : '11', + 'décembre' : '12' +} + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + modes.append({ + 'label' : 'Live TV', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_shows(params): + """Build shows listing""" + shows = [] + + if params.next == 'list_shows_1': + + for category_url, category_name in CATEGORIES.iteritems(): + + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=category_url, + category_name=category_name, + page='0', + next='list_videos_1', + window_title=category_name + ) + }) + + 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): + """Build videos listing""" + videos = [] + + if 'previous_listing' in params: + videos = ast.literal_eval(params['previous_listing']) + + url = params.category_url + '&page=' + str(params.page) + + file_path = utils.download_catalog( + url, + '%s_%s_%s.html' % ( + params.channel_name, + params.category_name, + params.page)) + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') + + if params.category_name == 'Politique': + video_soup = root_soup.find_all( + 'article', + class_="node node-episode node-episode-pse-search-result theme-4127 clearfix") + elif params.category_name == 'Société': + video_soup = root_soup.find_all( + 'article', + class_="node node-episode node-episode-pse-search-result theme-4126 clearfix") + elif params.category_name == 'Débat': + video_soup = root_soup.find_all( + 'article', + class_="node node-episode node-episode-pse-search-result theme-4128 clearfix") + + for video in video_soup: + + # Test Existing Video + if video.find('div', class_="content").find( \ + 'div', class_="right").find('div', class_="wrapper-duree"): + + title = '' + if video.find('div', class_="content").find( \ + 'div', + class_="field field-name-title-field field-type-text field-label-hidden"): + title = video.find( + 'div', + class_="content" + ).find( + 'div', + class_="field field-name-field-ref-emission field-type-entityreference field-label-hidden" + ).find( + 'div', + class_="field-items" + ).find( + 'div', + class_="field-item even" + ).get_text().encode('utf-8') + ' - ' \ + + video.find( + 'div', + class_="content" + ).find( + 'div', + class_="field field-name-title-field field-type-text field-label-hidden" + ).find( + 'div', + class_="field-items" + ).find( + 'div', + class_="field-item even" + ).get_text().encode('utf-8') + else: + title = video.find( + 'div', + class_="content" + ).find( + 'div', + class_="field field-name-field-ref-emission field-type-entityreference field-label-hidden" + ).find( + 'div', + class_="field-items" + ).find( + 'div', + class_="field-item even" + ).get_text().encode('utf-8') + + img = '' + if video.find('div', class_="content").find('div', class_="wrapper-visuel" \ + ).find('div', class_="scald-atom video").find('div', \ + class_="field field-name-scald-thumbnail field-type-image field-label-hidden"): + img = video.find( + 'div', + class_="content" + ).find( + 'div', + class_="wrapper-visuel" + ).find( + 'div', + class_="scald-atom video" + ).find( + 'div', + class_="field field-name-scald-thumbnail field-type-image field-label-hidden" + ).find( + 'div', + class_="field-items" + ).find( + 'div', + class_="field-item even" + ).find('img').get('src') + + plot = '' + if video.find('div', class_="content").find('div', \ + class_="field field-name-field-contenu field-type-text-long field-label-hidden"): + plot = video.find( + 'div', + class_="content" + ).find( + 'div', + class_="field field-name-field-contenu field-type-text-long field-label-hidden" + ).find( + 'div', + class_="field-items" + ).find( + 'div', + class_="field-item even" + ).get_text().encode('utf-8') + + + value_date = video.find( + 'div', + class_="content" + ).find('div', class_="first-diffusion").get_text().encode('utf-8') + date = value_date.split(' ') + day = date[2] + try: + mounth = CORRECT_MONTH[date[3]] + except: + mounth = '00' + year = date[4] + + date = '.'.join((day, mounth, year)) + aired = '-'.join((year, mounth, day)) + + duration = 0 + duration = int(video.find('div', class_="content").find( + 'div', class_="right").find( + 'div', + class_="wrapper-duree").get_text().encode('utf-8')[:-3]) * 60 + + + url_video = URL_ROOT + video.find( + 'div', class_="content").find('a').get('href').encode('utf-8') + + info = { + 'video': { + 'title': title, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': year, + 'plot' : plot, + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + url_video=url_video) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': img, + 'fanart': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + url_video=url_video + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + # More videos... + videos.append({ + 'label': common.ADDON.get_localized_string(30100), + 'url': common.PLUGIN.get_url( + action='channel_entry', + category_url=params.category_url, + category_name=params.category_name, + next='list_videos_1', + page=str(int(params.page) + 1), + update_listing=True, + previous_listing=str(videos) + ), + }) + + return common.PLUGIN.create_listing( + videos, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_PLAYCOUNT, + common.sp.xbmcplugin.SORT_METHOD_DATE, + common.sp.xbmcplugin.SORT_METHOD_DURATION, + common.sp.xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE + ), + content='tvshows', + update_listing='update_listing' in params, + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] + + title = '' + plot = '' + duration = 0 + img = '' + url_live = '' + + html_live = utils.get_webcontent(URL_LIVE_SITE) + root_soup = bs(html_live, 'html.parser') + live_soup = root_soup.find( + 'div', + class_='iframe-responsive') + + url_live = live_soup.find('iframe').get('src') + + title = '%s Live' % params.channel_name.upper() + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } + + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + url=url_live, + ), + 'is_playable': True, + 'info': info + }) + + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) + +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + if params.next == 'play_r' or params.next == 'download_video': + + url = '' + + html_video = utils.get_webcontent(params.url_video) + ur_video_soup = bs(html_video, 'html.parser') + urlembeded_videos_soup = ur_video_soup.find_all('iframe') + + for url in urlembeded_videos_soup: + url_video_embed = url.get('src').encode('utf-8') + break # get first video hard to find by another method + + + url_video_embed_http = url_video_embed + if params.next == 'download_video': + return url_video_embed_http + html_video = utils.get_webcontent(url_video_embed_http) + html_video = html_video.replace('\\', '') + + all_url_video = re.compile(r'"type":"video/mp4","url":"(.*?)"').findall(html_video) + for datas in all_url_video: + url = datas + + return url + + elif params.next == 'play_l': + + html_live = utils.get_webcontent(params.url) + html_live = html_live.replace('\\', '') + + url_live = re.compile( + r'{"type":"application/x-mpegURL","url":"(.*?)"}]}').findall(html_live) + + # Just one flux no quality to choose + return url_live[0] diff --git a/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py b/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py index ae6053c..79c524c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py +++ b/plugin.video.catchuptvandmore/resources/lib/channels/fr/tf1.py @@ -21,101 +21,194 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ +import json from bs4 import BeautifulSoup as bs from resources.lib import utils from resources.lib import common -import json -url_root = "http://www.tf1.fr/" -url_time = 'http://www.wat.tv/servertime2/' -url_token = 'http://api.wat.tv/services/Delivery' +# TO DO +# Rework QUALITY +# Replay LCI (Add date, aired, year, fix some elements) + +# Initialize GNU gettext emulation in addon +# This allows to use UI strings from addon’s English +# strings.po file instead of numeric codes +_ = common.ADDON.initialize_gettext() + +URL_ROOT = "http://www.tf1.fr/" +URL_TIME = 'http://www.wat.tv/servertime2/' +URL_TOKEN = 'http://api.wat.tv/services/Delivery' +URL_LIVE_TV = 'https://www.tf1.fr/%s/direct' +URL_LIVE_INFO = 'https://api.mytf1.tf1.fr/live/2/%s' +URL_API_IMAGE = 'http://api.mytf1.tf1.fr/image' -secret_key = 'W3m0#1mFI' -app_name = 'sdk/Iphone/1.0' -version = '2.1.3' -hosting_application_name = 'com.tf1.applitf1' -hosting_application_version = '7.0.4' +URL_LCI_REPLAY = "http://www.lci.fr/emissions" +URL_LCI_ROOT = "http://www.lci.fr" + +SECRET_KEY = 'W3m0#1mFI' +APP_NAME = 'sdk/Iphone/1.0' +VERSION = '2.1.3' +HOSTING_APPLICATION_NAME = 'com.tf1.applitf1' +HOSTING_APPLICATION_VERSION = '7.0.4' +IMG_WIDTH = 640 +IMG_HEIGHT = 360 def channel_entry(params): - if 'list_shows' in params.next: + """Entry function of the module""" + if 'root' in params.next: + return root(params) + elif 'list_shows' in params.next: return list_shows(params) elif 'list_videos_categories' in params.next: return list_videos_categories(params) elif 'list_videos' in params.next: return list_videos(params) + elif 'live' in params.next: + return list_live(params) elif 'play' in params.next: return get_video_url(params) - else: - return None - + return None + +@common.PLUGIN.cached(common.CACHE_TIME) +def root(params): + """Add Replay and Live in the listing""" + modes = [] + + # Add Replay + modes.append({ + 'label' : 'Replay', + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='list_shows_1', + category='%s Replay' % params.channel_name.upper(), + window_title='%s Replay' % params.channel_name.upper() + ), + }) + + # Add Live + if params.channel_name != 'tfou' and params.channel_name != 'xtra': + modes.append({ + 'label' : _('Live TV'), + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='live_cat', + category='%s Live TV' % params.channel_name.upper(), + window_title='%s Live TV' % params.channel_name.upper() + ), + }) + + return common.PLUGIN.create_listing( + modes, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ), + ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_shows(params): + """Build categories listing""" 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.channel_name == 'lci': - 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', - window_title=category_name - ) - }) + file_path = utils.download_catalog( + URL_LCI_REPLAY, + params.channel_name + '.html') + root_html = open(file_path).read() + root_soup = bs(root_html, 'html.parser') - 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') + if params.next == 'list_shows_1': + programs_soup = root_soup.find( + 'ul', + attrs={'class': 'topic-chronology-milestone-component'}) + for program in programs_soup.find_all('li'): + program_url = URL_LCI_ROOT + program.find('a')['href'].encode('utf-8') program_name = program.find( - 'p', - class_='program').get_text().encode('utf-8') - img = program.find('img') + 'h2', + class_='text-block').get_text().encode('utf-8') + img = program.find_all('source')[0] try: img = img['data-srcset'].encode('utf-8') except: img = img['srcset'].encode('utf-8') - img = 'http:' + img.split(',')[-1].split(' ')[0] + img = img.split(',')[0].split(' ')[0] shows.append({ 'label': program_name, 'thumb': img, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', program_url=program_url, - next='list_videos_categories', + next='list_videos', window_title=program_name ) }) + else: + 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') - return common.plugin.create_listing( + shows.append({ + 'label': category_name, + 'url': common.PLUGIN.get_url( + action='channel_entry', + category=category_url, + next='list_shows_2', + window_title=category_name + ) + }) + + 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_categories', + window_title=program_name + ) + }) + + return common.PLUGIN.create_listing( shows, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -124,11 +217,11 @@ def list_shows(params): ) -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos_categories(params): + """Build videos categories listing""" videos_categories = [] url = ''.join(( - url_root, params.program_url, '/videos')) program_html = utils.get_webcontent(url) @@ -141,16 +234,16 @@ def list_videos_categories(params): category_title = li.get_text().encode('utf-8') category_id = li.find('a')['data-filter'].encode('utf-8') videos_categories.append({ - 'label': category_title, - 'url': common.plugin.get_url( - action='channel_entry', - program_url=params.program_url, - next='list_videos', - window_title=category_title, - category_id=category_id - ) - }) - return common.plugin.create_listing( + 'label': category_title, + 'url': common.PLUGIN.get_url( + action='channel_entry', + program_url=params.program_url, + next='list_videos', + window_title=category_title, + category_id=category_id + ) + }) + return common.PLUGIN.create_listing( videos_categories, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_UNSORTED, @@ -159,97 +252,171 @@ def list_videos_categories(params): ) - -@common.plugin.cached(common.cache_time) +@common.PLUGIN.cached(common.CACHE_TIME) def list_videos(params): + """Build videos listing""" videos = [] - url = ''.join(( - url_root, - params.program_url, - '/videos/', - '?filter=', - params.category_id)) - program_html = utils.get_webcontent(url) - program_soup = bs(program_html, 'html.parser') + if params.channel_name == 'lci': + program_html = utils.get_webcontent(params.program_url) + program_soup = bs(program_html, 'html.parser') - grid = program_soup.find( - 'ul', - class_='grid') + list_replay = program_soup.find_all( + 'a', + class_='topic-emission-extract-block-image trackXiti') - for li in grid.find_all('li'): - video_type_string = li.find('div', class_='description').find('a')['data-xiti-libelle'].encode('utf-8') - video_type_string = video_type_string.split('-')[0] + for replay in list_replay: - if 'Playlist' not in video_type_string: - 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') + title = replay.find_all('img')[0].get('alt').encode('utf-8') + duration = 0 + img = replay.find_all('source')[0] 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] - aired = '' - - # day = aired.split('-')[2] - # mounth = aired.split('-')[1] - # year = aired.split('-')[0] - # date = '.'.join((day, mounth, year)) - date ='' - # date : string (%d.%m.%Y / 01.01.2009) - # aired : string (2008-12-07) - program_id = li.find('a')['href'].encode('utf-8') + img = img.split(',')[0].split(' ')[0] + program_id = URL_LCI_ROOT + replay.get('href').encode('utf-8') info = { 'video': { 'title': title, - 'plot': stitle, - 'aired': aired, - 'date': date, + #'plot': stitle, + #'aired': aired, + #'date': date, 'duration': duration, #'year': int(aired[:4]), 'mediatype': 'tvshow' } } + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + program_id=program_id) + ')' + ) + context_menu.append(download_video) + videos.append({ 'label': title, 'thumb': img, - 'url': common.plugin.get_url( + 'url': common.PLUGIN.get_url( action='channel_entry', - next='play', + next='play_r', program_id=program_id, ), 'is_playable': True, - 'info': info + 'info': info, + 'context_menu': context_menu }) - return common.plugin.create_listing( + else: + url = ''.join(( + params.program_url, + '/videos/', + '?filter=', + params.category_id)) + 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( + 'div', class_='description').find('a')['data-xiti-libelle'].encode('utf-8') + video_type_string = video_type_string.split('-')[0] + + if 'Playlist' not in video_type_string: + 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_soup = li.find( + 'p', + class_='uptitle').find( + 'span', + class_='momentDate') + duration = int(duration_soup.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] + + try: + date_soup = li.find( + 'div', + class_='text').find( + 'p', + class_='uptitle').find('span') + + aired = date_soup['data-date'].encode('utf-8').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) + + except: + date = '' + aired = '' + year = 0 + + program_id = li.find('a')['href'].encode('utf-8') + + info = { + 'video': { + 'title': title, + 'plot': stitle, + 'aired': aired, + 'date': date, + 'duration': duration, + 'year': int(aired[:4]), + 'mediatype': 'tvshow' + } + } + + context_menu = [] + download_video = ( + _('Download'), + 'XBMC.RunPlugin(' + common.PLUGIN.get_url( + action='download_video', + program_id=program_id) + ')' + ) + context_menu.append(download_video) + + videos.append({ + 'label': title, + 'thumb': img, + 'url': common.PLUGIN.get_url( + action='channel_entry', + next='play_r', + program_id=program_id, + ), + 'is_playable': True, + 'info': info, + 'context_menu': context_menu + }) + + return common.PLUGIN.create_listing( videos, sort_methods=( common.sp.xbmcplugin.SORT_METHOD_DATE, @@ -259,58 +426,176 @@ def list_videos(params): ), content='tvshows') +@common.PLUGIN.cached(common.CACHE_TIME) +def list_live(params): + """Build live listing""" + lives = [] -@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') + file_path = utils.download_catalog( + URL_LIVE_INFO % params.channel_name, + '%s_info_live.json' % (params.channel_name) + ) + file_info_live = open(file_path).read() + json_parser = json.loads(file_info_live) + + title = json_parser["current"]["title"].encode('utf-8') + ' - ' \ + + json_parser["current"]["episode"].encode('utf-8') + if "description" in json_parser["current"]: + plot = json_parser["current"]["humanStartDate"].encode('utf-8') + ' - ' \ + + json_parser["current"]["humanEndDate"].encode('utf-8') \ + + '\n ' + json_parser["current"]["description"].encode('utf-8') + else: + plot = json_parser["current"]["humanStartDate"].encode('utf-8') + ' - ' \ + + json_parser["current"]["humanEndDate"].encode('utf-8') + + duration = 0 + #duration = json_parser["videoJsonPlayer"]["videoDurationSeconds"] + + # Get Image (Code java found in a Forum) + id_image = json_parser["current"]["image"].encode('utf-8') + value_md5 = common.sp.md5(str(IMG_WIDTH) + str(IMG_HEIGHT) + id_image \ + + 'elk45sz6ers68').hexdigest() + value_md5 = value_md5[:6] + try: + img = URL_API_IMAGE + '/' + str(IMG_WIDTH) + '/' + str(IMG_HEIGHT) + '/' \ + + id_image + '/' + str(value_md5) + except: + img = '' + + info = { + 'video': { + 'title': title, + 'plot': plot, + 'duration': duration + } + } - iframe_player_soup = video_html_soup.find( - 'div', - class_='iframe_player') + lives.append({ + 'label': title, + 'fanart': img, + 'thumb': img, + 'url' : common.PLUGIN.get_url( + action='channel_entry', + next='play_l', + ), + 'is_playable': True, + 'info': info + }) - data_src = iframe_player_soup['data-src'].encode('utf-8') - video_id = data_src[-8:] + return common.PLUGIN.create_listing( + lives, + sort_methods=( + common.sp.xbmcplugin.SORT_METHOD_UNSORTED, + common.sp.xbmcplugin.SORT_METHOD_LABEL + ) + ) - timeserver = str(utils.get_webcontent(url_time)) +@common.PLUGIN.cached(common.CACHE_TIME) +def get_video_url(params): + """Get video URL and start video player""" + + if params.next == 'play_r' or params.next == 'download_video': + if "http" not in params.program_id: + if params.program_id[0] == '/': + params.program_id = params.program_id[1:] + url = URL_ROOT + params.program_id + else: + url = 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') + + if params.channel_name == 'lci': + video_id = iframe_player_soup['data-watid'].encode('utf-8') + else: + data_src = iframe_player_soup['data-src'].encode('utf-8') + video_id = data_src[-8:] + + timeserver = str(utils.get_webcontent(URL_TIME)) + + auth_key = '%s-%s-%s-%s-%s' % ( + video_id, + SECRET_KEY, + APP_NAME, + SECRET_KEY, + timeserver + ) - auth_key = '%s-%s-%s-%s-%s' % ( - video_id, - secret_key, - app_name, - secret_key, - timeserver - ) + auth_key = common.sp.md5(auth_key).hexdigest() + auth_key = auth_key + '/' + timeserver + + post_data = { + 'appName': APP_NAME, + 'method': 'getUrl', + 'mediaId': video_id, + 'authKey': auth_key, + 'version': VERSION, + 'hostingApplicationName': HOSTING_APPLICATION_NAME, + 'hostingApplicationVersion': HOSTING_APPLICATION_VERSION + } + + url_video = utils.get_webcontent( + url=URL_TOKEN, + request_type='post', + post_dic=post_data) + url_video = json.loads(url_video) + url_video = url_video['message'].replace('\\', '') + + desired_quality = common.PLUGIN.get_setting('quality') + + if desired_quality == 'BEST' or desired_quality == 'DIALOG': + try: + url_video = url_video.split('&bwmax')[0] + except: + pass - auth_key = common.sp.md5(auth_key).hexdigest() - auth_key = auth_key + '/' + timeserver - - post_data = { - 'appName': app_name, - 'method': 'getUrl', - 'mediaId': video_id, - 'authKey': auth_key, - 'version': version, - 'hostingApplicationName': hosting_application_name, - 'hostingApplicationVersion': hosting_application_version - } + return url_video + + elif params.next == 'play_l': + + # Video_ID 'L_%CHANNEL_NAME%' + video_id = 'L_%s' % params.channel_name.upper() - url_video = utils.get_webcontent( - url=url_token, - request_type='post', - post_dic=post_data) - url_video = json.loads(url_video) - url_video = url_video['message'].replace('\\', '') + timeserver = str(utils.get_webcontent(URL_TIME)) - desired_quality = common.plugin.get_setting( - params.channel_id + '.quality') + auth_key = '%s-%s-%s-%s-%s' % ( + video_id, + SECRET_KEY, + APP_NAME, + SECRET_KEY, + timeserver + ) - if desired_quality == 'Force HD': - try: - url_video = url_video.split('&bwmax')[0] - except: - pass + auth_key = common.sp.md5(auth_key).hexdigest() + auth_key = auth_key + '/' + timeserver + + post_data = { + 'appName': APP_NAME, + 'method': 'getUrl', + 'mediaId': video_id, + 'authKey': auth_key, + 'version': VERSION, + 'hostingApplicationName': HOSTING_APPLICATION_NAME, + 'hostingApplicationVersion': HOSTING_APPLICATION_VERSION + } + + url_video = utils.get_webcontent( + url=URL_TOKEN, + request_type='post', + post_dic=post_data) + url_video = json.loads(url_video) + url_video = url_video['message'].replace('\\', '') + + desired_quality = common.PLUGIN.get_setting('quality') + + if desired_quality == 'BEST' or desired_quality == 'DIALOG': + try: + url_video = url_video.split('&bwmax')[0] + except: + pass - return url_video
\ No newline at end of file + return url_video diff --git a/plugin.video.catchuptvandmore/resources/lib/common.py b/plugin.video.catchuptvandmore/resources/lib/common.py index aea8366..f403d7f 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/common.py +++ b/plugin.video.catchuptvandmore/resources/lib/common.py @@ -19,21 +19,21 @@ 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 resources.lib import simpleplugin as sp -import os -plugin = sp.Plugin() -addon = sp.Addon() +import os +from resources.lib import simpleplugin as sp -cache_time = 10 +PLUGIN = sp.Plugin() +ADDON = sp.Addon() -plugin_name = 'Catch-up TV & More' +CACHE_TIME = 10 +PLUGIN_NAME = 'Catch-up TV & More' def get_window_title(): query = sp.sys.argv[2][1:] - params = plugin.get_params(query) + params = PLUGIN.get_params(query) if 'window_title' in params: return params.window_title else: - return plugin_name + return PLUGIN_NAME diff --git a/plugin.video.catchuptvandmore/resources/lib/simpleplugin.py b/plugin.video.catchuptvandmore/resources/lib/simpleplugin.py index f3b6f9d..f3b6f9d 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/simpleplugin.py +++ b/plugin.video.catchuptvandmore/resources/lib/simpleplugin.py diff --git a/plugin.video.catchuptvandmore/resources/lib/skeleton.py b/plugin.video.catchuptvandmore/resources/lib/skeleton.py index d8546d4..7d2f9a2 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/skeleton.py +++ b/plugin.video.catchuptvandmore/resources/lib/skeleton.py @@ -21,40 +21,57 @@ """ -categories = { - 'main_menu.fr': 'French channels' - # 'main_menu.be': 'Belgian channels' +CATEGORIES = { + 'main_menu.fr': 'French channels', + 'main_menu.eu': 'European channels' } -channels = { +CHANNELS = { 'main_menu.fr': { 'channels.fr.tf1.tf1': 'TF1', 'channels.fr.pluzz.france2': 'France 2', 'channels.fr.pluzz.france3': 'France 3', - 'channels.fr.canalplus.canalplus': 'Canal +', + 'channels.fr.groupecanal.cplus': 'Canal +', 'channels.fr.pluzz.france5': 'France 5', 'channels.fr.6play.m6': 'M6', - 'channels.fr.arte.arte': 'Arte', - 'channels.fr.c.c8': 'C8', + 'channels.fr.groupecanal.c8': 'C8', 'channels.fr.6play.w9': 'W9', 'channels.fr.tf1.tmc': 'TMC', 'channels.fr.tf1.nt1': 'NT1', 'channels.fr.nrj.nrj12': 'NRJ 12', 'channels.fr.pluzz.france4': 'France 4', 'channels.fr.bfmtv.bfmtv': 'BFM TV', - 'channels.fr.itele.itele': 'i-Télé', - 'channels.fr.c.cstar': 'CStar', + 'channels.fr.groupecanal.cnews': 'CNews', + 'channels.fr.groupecanal.cstar': 'CStar', 'channels.fr.gulli.gulli': 'Gulli', 'channels.fr.pluzz.franceo': 'France Ô', 'channels.fr.tf1.hd1': 'HD1', 'channels.fr.lequipe.lequipe': 'L\'Équipe', 'channels.fr.6play.6ter': '6ter', 'channels.fr.numero23.numero23': 'Numéro 23', - 'channels.fr.nrj.cherie25': 'Chérie 25' + 'channels.fr.nrj.cherie25': 'Chérie 25', + 'channels.fr.pluzz.la_1ere': 'La 1ère (Outre-Mer)', + 'channels.fr.pluzz.franceinfo': 'France Info', + 'channels.fr.bfmtv.bfmbusiness': 'BFM Business', + 'channels.fr.bfmtv.rmc': 'RMC', + 'channels.fr.bfmtv.01net': '01Net TV', + 'channels.fr.tf1.tfou': 'Tfou (MYTF1)', + 'channels.fr.tf1.xtra': 'Xtra (MYTF1)', + 'channels.fr.tf1.lci': 'LCI', + 'channels.fr.lcp.lcp': 'LCP Assemblée Nationale', + 'channels.fr.bfmtv.rmcdecouverte': 'RMC Découverte HD24', + 'channels.fr.6play.stories': 'Stories (6play)', + 'channels.fr.6play.bruce': 'Bruce (6play)', + 'channels.fr.6play.crazy_kitchen': 'Crazy Kitchen (6play)', + 'channels.fr.6play.home': 'Home Time (6play)', + 'channels.fr.6play.styles': 'Sixième Style (6play)', + 'channels.fr.6play.comedy': 'Comic (6play)', + 'channels.fr.france24.france24': 'France 24', + 'channels.fr.publicsenat.publicsenat': 'Public Sénat' + }, + 'main_menu.eu': { + 'channels.eu.arte.arte': 'Arte', + 'channels.eu.euronews.euronews': 'Euronews' } - - # 'main_menu.be': { - # 'channels.be.rtbf.rtbf': 'RTBF' - # } } diff --git a/plugin.video.catchuptvandmore/resources/lib/utils.py b/plugin.video.catchuptvandmore/resources/lib/utils.py index 5123afb..e9206df 100644..100755 --- a/plugin.video.catchuptvandmore/resources/lib/utils.py +++ b/plugin.video.catchuptvandmore/resources/lib/utils.py @@ -31,16 +31,16 @@ from resources.lib import common user_data = common.sp.xbmc.translatePath( os.path.join( 'special://profile/addon_data', - common.addon.id)) + common.ADDON.id)) cache_path = common.sp.xbmc.translatePath( os.path.join( user_data, 'cache')) -default_ua = "Mozilla/5.0 (Windows NT 6.1; WOW64) " \ +default_ua = "Mozilla/5.0 (X11; Linux x86_64) " \ "AppleWebKit/537.36 (KHTML, like Gecko) " \ - "Chrome/55.0.2883.87 Safari/537.36" + "Chrome/60.0.3112.78 Safari/537.36" user_agents = [ 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36' @@ -74,7 +74,7 @@ def download_catalog( specific_headers={}, params={}): file_name = format_filename(file_name) - common.addon.log('URL download_catalog : ' + url) + common.ADDON.log('URL download_catalog : ' + url) if not os.path.exists(cache_path): os.makedirs(cache_path, mode=0777) @@ -124,7 +124,7 @@ def get_webcontent( random_ua=False, specific_headers={}, params={}): - common.addon.log('URL get_webcontent : ' + url) + common.ADDON.log('URL get_webcontent : ' + url) if random_ua: ua = user_agents[randint(0, len(user_agents) - 1)] else: @@ -167,6 +167,6 @@ def get_redirected_url( def send_notification( - message, title=common.plugin_name, time=5000, sound=True): + message, title=common.PLUGIN_NAME, time=5000, sound=True): common.sp.xbmcgui.Dialog().notification( - title, message, common.addon.icon, time) + title, message, common.ADDON.icon, time) diff --git a/plugin.video.catchuptvandmore/resources/media/categories/eu.png b/plugin.video.catchuptvandmore/resources/media/categories/eu.png Binary files differnew file mode 100755 index 0000000..e534746 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/categories/eu.png diff --git a/plugin.video.catchuptvandmore/resources/media/categories/fr.png b/plugin.video.catchuptvandmore/resources/media/categories/fr.png Binary files differnew file mode 100755 index 0000000..cb017dc --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/categories/fr.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/arte.png b/plugin.video.catchuptvandmore/resources/media/channels/eu/arte.png Binary files differindex 3c003a2..3c003a2 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/arte.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/eu/arte.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/eu/arte_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/eu/arte_fanart.png Binary files differnew file mode 100755 index 0000000..dd5491b --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/eu/arte_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews.png b/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews.png Binary files differnew file mode 100755 index 0000000..0b40147 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews_fanart.png Binary files differnew file mode 100755 index 0000000..a05737f --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/eu/euronews_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/01net.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/01net.png Binary files differnew file mode 100755 index 0000000..10e36e0 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/01net.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/01net_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/01net_fanart.png Binary files differnew file mode 100755 index 0000000..c793db8 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/01net_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter.png Binary files differindex 320cf16..320cf16 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter_fanart.png Binary files differindex 0fdefb5..0fdefb5 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/6ter_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness.png Binary files differnew file mode 100755 index 0000000..8286439 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness_fanart.png Binary files differnew file mode 100755 index 0000000..a849cda --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmbusiness_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv.png Binary files differindex 3ca5f2a..3ca5f2a 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv_fanart.png Binary files differindex 226487f..226487f 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bfmtv_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce.png Binary files differnew file mode 100755 index 0000000..4d043f5 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce_fanart.png Binary files differnew file mode 100755 index 0000000..fd37443 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/bruce_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/c8.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/c8.png Binary files differindex e18d86c..e18d86c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/c8.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/c8.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/c8_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/c8_fanart.png Binary files differindex 05a9a6c..05a9a6c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/c8_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/c8_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25.png Binary files differindex f4f9d60..f4f9d60 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25_fanart.png Binary files differnew file mode 100755 index 0000000..6ecbd9e --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cherie25_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews.png Binary files differnew file mode 100755 index 0000000..a3f5127 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews_fanart.png Binary files differnew file mode 100755 index 0000000..a759d39 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cnews_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy.png Binary files differnew file mode 100755 index 0000000..279348c --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy_fanart.png Binary files differnew file mode 100755 index 0000000..f2a41c1 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/comedy_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/canalplus.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cplus.png Binary files differindex 6829f23..6829f23 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/canalplus.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cplus.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/canalplus_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cplus_fanart.png Binary files differindex 2a2e3b4..2a2e3b4 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/canalplus_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cplus_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen.png Binary files differnew file mode 100755 index 0000000..6d8c2d2 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen_fanart.png Binary files differnew file mode 100755 index 0000000..1e03344 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/crazy_kitchen_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar.png Binary files differindex 4d3a463..4d3a463 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar_fanart.png Binary files differindex f7c45db..f7c45db 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/cstar_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france2.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france2.png Binary files differindex 6f741cd..6f741cd 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france2.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france2.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france24.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france24.png Binary files differnew file mode 100755 index 0000000..9a9db7c --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france24.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france24_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france24_fanart.png Binary files differnew file mode 100755 index 0000000..dadb2fb --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france24_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france2_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france2_fanart.png Binary files differindex 8184c2a..8184c2a 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france2_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france2_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france3.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france3.png Binary files differindex 3309012..3309012 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france3.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france3.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france3_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france3_fanart.png Binary files differindex dede4f8..dede4f8 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france3_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france3_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france4.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france4.png Binary files differindex a8a1bba..a8a1bba 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france4.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france4.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france4_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france4_fanart.png Binary files differnew file mode 100755 index 0000000..d83de13 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france4_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france5.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france5.png Binary files differindex bc1f6ea..bc1f6ea 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/france5.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france5.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/france5_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/france5_fanart.png Binary files differnew file mode 100755 index 0000000..96ce7ae --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/france5_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo.png Binary files differnew file mode 100755 index 0000000..bdc12e4 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo_fanart.png Binary files differnew file mode 100755 index 0000000..edb1cb8 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceinfo_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo.png Binary files differindex b2de049..b2de049 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo_fanart.png Binary files differnew file mode 100755 index 0000000..e05df4c --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/franceo_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli.png Binary files differindex b2e1522..b2e1522 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli_fanart.png Binary files differindex 94739ab..94739ab 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/gulli_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1.png Binary files differindex c33450f..c33450f 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1_fanart.png Binary files differindex 665dc6c..665dc6c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/hd1_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/home.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/home.png Binary files differnew file mode 100755 index 0000000..3c3f68f --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/home.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/home_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/home_fanart.png Binary files differnew file mode 100755 index 0000000..1c22df9 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/home_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/itele.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/itele.png Binary files differdeleted file mode 100644 index 2e1d937..0000000 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/itele.png +++ /dev/null diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/itele_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/itele_fanart.png Binary files differdeleted file mode 100644 index 1bca166..0000000 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/itele_fanart.png +++ /dev/null diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere.png Binary files differnew file mode 100755 index 0000000..29de8d2 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere_fanart.png Binary files differnew file mode 100755 index 0000000..1dcc660 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/la_1ere_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lci.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lci.png Binary files differnew file mode 100755 index 0000000..c979af1 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lci.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lci_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lci_fanart.png Binary files differnew file mode 100755 index 0000000..565bdee --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lci_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp.png Binary files differnew file mode 100755 index 0000000..d33817d --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp_fanart.png Binary files differnew file mode 100755 index 0000000..d697fdf --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lcp_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe.png Binary files differindex 90b5b46..90b5b46 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe_fanart.png Binary files differindex bfc2dbe..bfc2dbe 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/lequipe_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/m6.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/m6.png Binary files differindex 24852b7..24852b7 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/m6.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/m6.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/m6_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/m6_fanart.png Binary files differindex f5e8e8e..f5e8e8e 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/m6_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/m6_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12.png Binary files differindex 0c4c9f4..0c4c9f4 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12_fanart.png Binary files differindex 848d9c6..848d9c6 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/nrj12_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1.png Binary files differindex 59c8e33..59c8e33 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1_fanart.png Binary files differindex bc00729..bc00729 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/nt1_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23.png Binary files differindex c6f154f..cd302c4 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23_fanart.png Binary files differnew file mode 100755 index 0000000..35045dd --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/numero23_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere.png Binary files differnew file mode 100755 index 0000000..83ad901 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere_fanart.png Binary files differnew file mode 100755 index 0000000..823bd90 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/parispremiere_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat.png Binary files differnew file mode 100755 index 0000000..8a756d9 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat_fanart.png Binary files differnew file mode 100755 index 0000000..38fc4bb --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/publicsenat_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc.png Binary files differnew file mode 100755 index 0000000..21bbe7e --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc_fanart.png Binary files differnew file mode 100755 index 0000000..d471802 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmc_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/rmcdecouverte.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmcdecouverte.png Binary files differnew file mode 100755 index 0000000..5908627 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/rmcdecouverte.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/stories.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/stories.png Binary files differnew file mode 100755 index 0000000..716f06a --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/stories.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/stories_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/stories_fanart.png Binary files differnew file mode 100755 index 0000000..4083644 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/stories_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/styles.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/styles.png Binary files differnew file mode 100755 index 0000000..84bb4b5 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/styles.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/styles_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/styles_fanart.png Binary files differnew file mode 100755 index 0000000..120a167 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/styles_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/teva.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/teva.png Binary files differnew file mode 100755 index 0000000..e376edf --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/teva.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/teva_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/teva_fanart.png Binary files differnew file mode 100755 index 0000000..b45bff7 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/teva_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1.png Binary files differindex 18b7490..18b7490 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1_fanart.png Binary files differindex e23d730..e23d730 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tf1_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou.png Binary files differnew file mode 100755 index 0000000..1b69f8d --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou_fanart.png Binary files differnew file mode 100755 index 0000000..f47d92d --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tfou_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc.png Binary files differindex 2ad9872..2ad9872 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc_fanart.png Binary files differindex de8fef7..de8fef7 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc_fanart.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/tmc_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/w9.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/w9.png Binary files differindex a0c27c4..a0c27c4 100644..100755 --- a/plugin.video.catchuptvandmore/resources/media/channels/fr/w9.png +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/w9.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/w9_fanart.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/w9_fanart.png Binary files differnew file mode 100755 index 0000000..0fe0102 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/w9_fanart.png diff --git a/plugin.video.catchuptvandmore/resources/media/channels/fr/xtra.png b/plugin.video.catchuptvandmore/resources/media/channels/fr/xtra.png Binary files differnew file mode 100755 index 0000000..dc311d1 --- /dev/null +++ b/plugin.video.catchuptvandmore/resources/media/channels/fr/xtra.png diff --git a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-01.jpg b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-01.jpg Binary files differindex 11c6c33..11c6c33 100644..100755 --- a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-01.jpg +++ b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-01.jpg diff --git a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-02.jpg b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-02.jpg Binary files differindex da9e325..da9e325 100644..100755 --- a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-02.jpg +++ b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-02.jpg diff --git a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-03.jpg b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-03.jpg Binary files differindex a5c6b9c..a5c6b9c 100644..100755 --- a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-03.jpg +++ b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-03.jpg diff --git a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-04.jpg b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-04.jpg Binary files differindex 05ee326..05ee326 100644..100755 --- a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-04.jpg +++ b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-04.jpg diff --git a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-05.jpg b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-05.jpg Binary files differindex f7d309f..f7d309f 100644..100755 --- a/plugin.video.catchuptvandmore/resources/screenshots/screenshot-05.jpg +++ b/plugin.video.catchuptvandmore/resources/screenshots/screenshot-05.jpg diff --git a/plugin.video.catchuptvandmore/resources/settings.xml b/plugin.video.catchuptvandmore/resources/settings.xml index af6fdaa..5037cbb 100644..100755 --- a/plugin.video.catchuptvandmore/resources/settings.xml +++ b/plugin.video.catchuptvandmore/resources/settings.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <settings> - + <!-- Main menu --> <category label="30000"> <!-- Hide main menu categories --> <setting label="30010" type="lsep"/> - <setting label="30020" type="bool" id="main_menu.fr" default="true"/> - <!-- <setting label="30021" type="bool" id="main_menu.be" default="true"/> --> + <setting label="30020" type="bool" id="main_menu.fr" default="true"/> + <setting label="30023" type="bool" id="main_menu.eu" default="true"/> </category> @@ -14,147 +14,185 @@ <category label="30001"> <!-- Hide channels from categories --> <setting label="30011" type="lsep"/> + <setting label="30020" type="lsep" subsetting="true" visible="eq(1,true)"/> <setting label="30020" type="bool" id="main_menu.fr" default="true" visible="false"/> <setting label="TF1" type="bool" id="channels.fr.tf1.tf1" default="true" visible="eq(-1,true)"/> <setting label="" type="number" visible="false" id="channels.fr.tf1.tf1.order" default="1"/> - + <setting label="France 2" type="bool" id="channels.fr.pluzz.france2" default="true" visible="eq(-3,true)"/> <setting label="" type="number" visible="false" id="channels.fr.pluzz.france2.order" default="2"/> - + <setting label="France 3" type="bool" id="channels.fr.pluzz.france3" default="true" visible="eq(-5,true)"/> <setting label="" type="number" visible="false" id="channels.fr.pluzz.france3.order" default="3"/> - - <setting label="Canal +" type="bool" id="channels.fr.canalplus.canalplus" default="true" visible="eq(-7,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.canalplus.canalplus.order" default="4"/> - + + <setting label="Canal +" type="bool" id="channels.fr.groupecanal.cplus" default="true" visible="eq(-7,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.groupecanal.cplus.order" default="4"/> + <setting label="France 5" type="bool" id="channels.fr.pluzz.france5" default="true" visible="eq(-9,true)"/> <setting label="" type="number" visible="false" id="channels.fr.pluzz.france5.order" default="5"/> - + <setting label="M6" type="bool" id="channels.fr.6play.m6" default="true" visible="eq(-11,true)"/> <setting label="" type="number" visible="false" id="channels.fr.6play.m6.order" default="6"/> - - <setting label="Arte" type="bool" id="channels.fr.arte.arte" default="true" visible="eq(-13,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.arte.arte.order" default="7"/> - - <setting label="C8" type="bool" id="channels.fr.c.c8" default="true" visible="eq(-15,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.c.c8.order" default="8"/> - - <setting label="W9" type="bool" id="channels.fr.6play.w9" default="true" visible="eq(-17,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.6play.w9.order" default="9"/> - - <setting label="TMC" type="bool" id="channels.fr.tf1.tmc" default="true" visible="eq(-19,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.tf1.tmc.order" default="10"/> - - <setting label="NT1" type="bool" id="channels.fr.tf1.nt1" default="true" visible="eq(-21,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.tf1.nt1.order" default="11"/> - - <setting label="NRJ 12" type="bool" id="channels.fr.nrj.nrj12" default="true" visible="eq(-23,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.nrj.nrj12.order" default="12"/> - - <setting label="France 4" type="bool" id="channels.fr.pluzz.france4" default="true" visible="eq(-25,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.pluzz.france4.order" default="14"/> - - <setting label="BFM TV" type="bool" id="channels.fr.bfmtv.bfmtv" default="true" visible="eq(-27,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.bfmtv.bfmtv.order" default="15"/> - - <setting label="i-Télé" type="bool" id="channels.fr.itele.itele" default="true" visible="eq(-29,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.itele.itele.order" default="16"/> - - <setting label="CStar" type="bool" id="channels.fr.c.cstar" default="true" visible="eq(-31,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.c.cstar.order" default="17"/> - - <setting label="Gulli" type="bool" id="channels.fr.gulli.gulli" default="true" visible="eq(-33,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.gulli.gulli.order" default="18"/> - - <setting label="France Ô" type="bool" id="channels.fr.pluzz.franceo" default="true" visible="eq(-35,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.pluzz.franceo.order" default="19"/> - - <setting label="HD1" type="bool" id="channels.fr.tf1.hd1" default="true" visible="eq(-37,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.tf1.hd1.order" default="20"/> - - <setting label="L'Équipe" type="bool" id="channels.fr.lequipe.lequipe" default="true" visible="eq(-39,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.lequipe.lequipe.order" default="21"/> - - <setting label="6ter" type="bool" id="channels.fr.6play.6ter" default="true" visible="eq(-41,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.6play.6ter.order" default="22"/> - - <setting label="Numéro 23" type="bool" id="channels.fr.numero23.numero23" default="true" visible="eq(-43,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.numero23.numero23.order" default="23"/> - - <setting label="Chérie 25" type="bool" id="channels.fr.nrj.cherie25" default="true" visible="eq(-45,true)"/> - <setting label="" type="number" visible="false" id="channels.fr.nrj.cherie25.order" default="25"/> -<!-- <setting label="30021" type="lsep" subsetting="true" visible="eq(1,true)"/> - <setting label="30021" type="bool" id="main_menu.be" default="true" visible="false"/> - <setting label="RTBF" type="bool" id="channels.be.rtbf.rtbf" default="true" visible="eq(-1,true)"/> --> - </category> + <setting label="C8" type="bool" id="channels.fr.groupecanal.c8" default="true" visible="eq(-13,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.groupecanal.c8.order" default="7"/> + <setting label="W9" type="bool" id="channels.fr.6play.w9" default="true" visible="eq(-15,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.w9.order" default="8"/> - <!-- Quality and content (and also hidden settings) --> - <category label="30002"> - - <setting label="30020" type="lsep" subsetting="true" visible="eq(1,true)"/> - <setting label="30020" type="bool" id="main_menu.fr" default="true" visible="false"/> - - <setting label="TF1" type="bool" id="channels.fr.tf1.tf1" default="true" visible="false"/> - <!-- <setting label="30070" type="bool" id="channels.fr.tf1.tf1.bonus" default="true" visible="eq(-1,true) + eq(-2,true)"/> --> - <setting label="30070" type="bool" id="channels.fr.tf1.tf1.bonus" default="true" visible="false"/> - <setting label="30087" type="labelenum" id="channels.fr.tf1.tf1.quality" visible="eq(-2,true) + eq(-3,true)" values="Force HD|Auto"/> + <setting label="TMC" type="bool" id="channels.fr.tf1.tmc" default="true" visible="eq(-17,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.tmc.order" default="9"/> + + <setting label="NT1" type="bool" id="channels.fr.tf1.nt1" default="true" visible="eq(-19,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.nt1.order" default="10"/> + + <setting label="NRJ 12" type="bool" id="channels.fr.nrj.nrj12" default="true" visible="eq(-21,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.nrj.nrj12.order" default="11"/> + + <setting label="France 4" type="bool" id="channels.fr.pluzz.france4" default="true" visible="eq(-23,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.pluzz.france4.order" default="12"/> + + <setting label="BFM TV" type="bool" id="channels.fr.bfmtv.bfmtv" default="true" visible="eq(-25,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.bfmtv.bfmtv.order" default="13"/> + + <setting label="CNews" type="bool" id="channels.fr.groupecanal.cnews" default="true" visible="eq(-27,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.groupecanal.cnews.order" default="14"/> + + <setting label="CStar" type="bool" id="channels.fr.groupecanal.cstar" default="true" visible="eq(-29,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.groupecanal.cstar.order" default="15"/> + + <setting label="Gulli" type="bool" id="channels.fr.gulli.gulli" default="true" visible="eq(-31,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.gulli.gulli.order" default="16"/> + + <setting label="France Ô" type="bool" id="channels.fr.pluzz.franceo" default="true" visible="eq(-33,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.pluzz.franceo.order" default="17"/> + + <setting label="HD1" type="bool" id="channels.fr.tf1.hd1" default="true" visible="eq(-35,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.hd1.order" default="18"/> + + <setting label="L'Équipe" type="bool" id="channels.fr.lequipe.lequipe" default="true" visible="eq(-37,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.lequipe.lequipe.order" default="19"/> + + <setting label="6ter" type="bool" id="channels.fr.6play.6ter" default="true" visible="eq(-39,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.6ter.order" default="20"/> + + <setting label="Numéro 23" type="bool" id="channels.fr.numero23.numero23" default="true" visible="eq(-41,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.numero23.numero23.order" default="21"/> + + <setting label="Chérie 25" type="bool" id="channels.fr.nrj.cherie25" default="true" visible="eq(-43,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.nrj.cherie25.order" default="22"/> + + <setting label="La 1ère (Outre-Mer)" type="bool" id="channels.fr.pluzz.la_1ere" default="true" visible="eq(-45,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.pluzz.la_1ere.order" default="23"/> + + <setting label="France Info" type="bool" id="channels.fr.pluzz.franceinfo" default="true" visible="eq(-47,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.pluzz.franceinfo.order" default="24"/> + + <setting label="BFM Business" type="bool" id="channels.fr.bfmtv.bfmbusiness" default="true" visible="eq(-49,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.bfmtv.bfmbusiness.order" default="25"/> - <setting label="France 2" type="bool" id="channels.fr.pluzz.france2" default="true" visible="false"/> - <setting label="30071" type="labelenum" id="channels.fr.pluzz.france2.quality" visible="eq(-1,true) + eq(-5,true)" values="HD|SD"/> + <setting label="RMC" type="bool" id="channels.fr.bfmtv.rmc" default="true" visible="eq(-51,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.bfmtv.rmc.order" default="26"/> - <setting label="France 3" type="bool" id="channels.fr.pluzz.france3" default="true" visible="false"/> - <setting label="30072" type="labelenum" id="channels.fr.pluzz.france3.quality" visible="eq(-1,true) + eq(-7,true)" values="HD|SD"/> + <setting label="01Net TV" type="bool" id="channels.fr.bfmtv.01net" default="true" visible="eq(-53,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.bfmtv.01net.order" default="27"/> - <setting label="France 5" type="bool" id="channels.fr.pluzz.france5" default="true" visible="false"/> - <setting label="30074" type="labelenum" id="channels.fr.pluzz.france5.quality" visible="eq(-1,true) + eq(-9,true)" values="HD|SD"/> - - <setting label="M6" type="bool" id="channels.fr.6play.m6" default="true" visible="false"/> - <setting label="30076" type="labelenum" id="channels.fr.6play.m6.quality" visible="eq(-1,true) + eq(-11,true)" values="Auto|Force HD|Force SD"/> - - <setting label="Arte" type="bool" id="channels.fr.arte.arte" default="true" visible="false"/> - <setting label="30079" type="labelenum" id="channels.fr.arte.arte.quality" visible="eq(-1,true) + eq(-13,true)" values="Auto|HD+|HD|SD|SD-"/> + <setting label="Tfou (MYTF1)" type="bool" id="channels.fr.tf1.tfou" default="true" visible="eq(-55,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.tfou.order" default="28"/> - <setting label="30080" type="labelenum" id="channels.fr.arte.arte.language" visible="eq(-2,true) + eq(-14,true)" values="Auto|fr|de"/> + <setting label="Xtra (MYTF1)" type="bool" id="channels.fr.tf1.xtra" default="true" visible="eq(-57,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.xtra.order" default="29"/> - <setting label="W9" type="bool" id="channels.fr.6play.w9" default="true" visible="false"/> - <setting label="30077" type="labelenum" id="channels.fr.6play.W9.quality" visible="eq(-1,true) + eq(-16,true)" values="Auto|Force HD|Force SD"/> - - <setting label="TMC" type="bool" id="channels.fr.tf1.tmc" default="true" visible="false"/> - <setting label="30082" type="bool" id="channels.fr.tf1.tmc.bonus" default="true" visible="eq(-1,true) + eq(-18,true)"/> + <setting label="LCI" type="bool" id="channels.fr.tf1.lci" default="true" visible="eq(-59,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.tf1.lci.order" default="30"/> - <setting label="NT1" type="bool" id="channels.fr.tf1.nt1" default="true" visible="false"/> - <setting label="30083" type="bool" id="channels.fr.tf1.nt1.bonus" default="true" visible="eq(-1,true) + eq(-20,true)"/> + <setting label="LCP Assemblée Nationale" type="bool" id="channels.fr.lcp.lcp" default="true" visible="eq(-61,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.lcp.lcp.order" default="31"/> - <setting label="NRJ 12" type="bool" id="channels.fr.nrj.nrj12" default="true" visible="false"/> - <setting label="30085" type="labelenum" id="channels.fr.nrj.nrj12.quality" visible="eq(-1,true) + eq(-22,true)" values="Auto|Force HD|Force SD"/> + <setting label="RMC Découverte HD24" type="bool" id="channels.fr.bfmtv.rmcdecouverte" default="true" visible="eq(-63,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.bfmtv.rmcdecouverte.order" default="32"/> - <setting label="France 4" type="bool" id="channels.fr.pluzz.france4" default="true" visible="false"/> - <setting label="30073" type="labelenum" id="channels.fr.pluzz.france4.quality" visible="eq(-1,true) + eq(-24,true)" values="HD|SD"/> + <setting label="Stories (6play)" type="bool" id="channels.fr.6play.stories" default="true" visible="eq(-65,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.stories.order" default="33"/> - <setting label="BFM TV" type="bool" id="channels.fr.bfmtv.bfmtv" default="true" visible="false"/> - <setting label="30081" type="labelenum" id="channels.fr.bfmtv.bfmtv.quality" visible="eq(-1,true) + eq(-26,true)" values="HD+|HD|SD|SD-"/> + <setting label="Bruce (6play)" type="bool" id="channels.fr.6play.bruce" default="true" visible="eq(-67,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.bruce.order" default="34"/> - <setting label="France Ô" type="bool" id="channels.fr.pluzz.franceo" default="true" visible="false"/> - <setting label="30075" type="labelenum" id="channels.fr.pluzz.franceo.quality" visible="eq(-1,true) + eq(-28,true)" values="HD|SD"/> + <setting label="Crazy Kitchen (6play)" type="bool" id="channels.fr.6play.crazy_kitchen" default="true" visible="eq(-69,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.crazy_kitchen.order" default="35"/> - <setting label="HD1" type="bool" id="channels.fr.tf1.hd1" default="true" visible="false"/> - <setting label="30084" type="bool" id="channels.fr.tf1.hd1.bonus" default="true" visible="eq(-1,true) + eq(-30,true)"/> + <setting label="Home Time (6play)" type="bool" id="channels.fr.6play.home" default="true" visible="eq(-71,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.home.order" default="36"/> - <setting label="6ter" type="bool" id="channels.fr.6play.6ter" default="true" visible="false"/> - <setting label="30078" type="labelenum" id="channels.fr.6play.6ter.quality" visible="eq(-1,true) + eq(-32,true)" values="Auto|Force HD|Force SD"/> + <setting label="Sixième Style (6play)" type="bool" id="channels.fr.6play.styles" default="true" visible="eq(-73,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.styles.order" default="37"/> - <setting label="L'Équipe" type="bool" id="channels.fr.lequipe.lequipe" default="true" visible="false"/> - <setting label="30086" type="labelenum" id="channels.fr.lequipe.lequipe.quality" visible="eq(-1,true) + eq(-34,true)" values="HD+|HD|SD"/> + <setting label="Comic (6play)" type="bool" id="channels.fr.6play.comedy" default="true" visible="eq(-75,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.comedy.order" default="38"/> - <setting label="Numéro 23" type="bool" id="channels.fr.numero23.numero23" default="true" visible="false"/> - <setting label="30088" type="labelenum" id="channels.fr.numero23.numero23.quality" visible="eq(-1,true) + eq(-36,true)" values="HD+|HD|SD"/> + <setting label="France24" type="bool" id="channels.fr.france24.france24" default="true" visible="eq(-77,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.france24.france24.order" default="39"/> + + <setting label="Public Sénat" type="bool" id="channels.fr.publicsenat.publicsenat" default="true" visible="eq(-79,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.publicsenat.publicsenat.order" default="40"/> + + <!--<setting label="Teva" type="bool" id="channels.fr.6play.teva" default="true" visible="eq(-81,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.teva.order" default="41"/> + + <setting label="Paris Première" type="bool" id="channels.fr.6play.parispremiere" default="true" visible="eq(-83,true)"/> + <setting label="" type="number" visible="false" id="channels.fr.6play.parispremiere.order" default="42"/>--> + + <setting label="30023" type="lsep" subsetting="true" visible="eq(1,true)"/> + <setting label="30023" type="bool" id="main_menu.eu" default="true" visible="false"/> + + <setting label="Euronews" type="bool" id="channels.eu.euronews.euronews" default="true" visible="eq(-1,true)"/> + <setting label="" type="number" visible="false" id="channels.eu.euronews.euronews.order" default="1"/> + + <setting label="Arte" type="bool" id="channels.eu.arte.arte" default="true" visible="eq(-3,true)"/> + <setting label="" type="number" visible="false" id="channels.eu.arte.arte.order" default="2"/> + + </category> + + + <!-- Quality and Content (and also hidden settings) --> + <category label="30002"> + + <setting label="30070" type="lsep" /> + <setting label="30087" type="labelenum" id="quality" values="BEST|DEFAULT|DIALOG"/> + + <setting label="30071" type="lsep" /> + <setting label="30020" type="lsep" subsetting="true" visible="eq(1,true)"/> + <setting label="30020" type="bool" id="main_menu.fr" default="true" visible="false"/> + + <setting label="30081" type="labelenum" id="channels.fr.france24.france24.language" visible="eq(-1,true)" values="FR|EN|AR"/> + + <setting label="30023" type="lsep" subsetting="true" visible="eq(1,true)"/> + <setting label="30023" type="bool" id="main_menu.eu" default="true" visible="false"/> + + <setting label="30080" type="labelenum" id="channels.eu.arte.arte.language" visible="eq(-1,true)" values="FR|DE"/> + <setting label="30082" type="labelenum" id="channels.eu.euronews.euronews.language" visible="eq(-2,true)" values="FR|EN|AR|DE|IT|ES|PT|RU|TR|FA|GR|HU"/> + + <setting label="" type="bool" id="show_hidden_items_information" default="true" visible="false"/> + </category> + + + <!-- Download ... --> + <category label="30003"> + <setting label="30012" type="lsep"/> + <setting label="30200" type="folder" id="dlFolder" source="auto" option="writeable"/> + </category> + + + <!-- Account ... --> + <category label="30004"> + + <setting label="30020" type="lsep" subsetting="true" visible="eq(1,true)"/> + <setting label="30020" type="bool" id="main_menu.fr" default="true" visible="false"/> - <setting label="" type="bool" id="show_hidden_items_information" default="true" visible="false"/> + <setting label="NRJ Login" type="text" id="channels.fr.nrj.login" visible="eq(-1,true)" defaut=""/> + <setting label="NRJ Password" type="text" id="channels.fr.nrj.password" option="hidden" visible="eq(-2,true)" defaut=""/> </category> - -</settings>
\ No newline at end of file +</settings> |