diff --git a/addon.xml b/addon.xml index b2242ee4..0d58e475 100644 --- a/addon.xml +++ b/addon.xml @@ -1,10 +1,6 @@ - + - - - - @@ -28,8 +24,10 @@ resources/media/screenshot-2.png resources/media/screenshot-3.png - - Corretto blocco nella ricerca globale - - migliorie e fix vari ai canali e al core + - Aggiunto menu globale "opzioni di KoD" +- Aggiunto canale tapmovie e server annessi +- Notifica quando il tipo di vista viene salvata (con indicazione del tipo di contenuto) + Naviga velocemente sul web e guarda i contenuti presenti [COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR] [COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR] diff --git a/channels.json b/channels.json index 7ab67f6c..5ae7e2d9 100644 --- a/channels.json +++ b/channels.json @@ -22,7 +22,7 @@ "filmigratis": "https://filmigratis.org", "guardaseriecam": "https://guardaserie.cam", "guardaserieclick": "https://www.guardaserie.builders", - "guardaserieicu": "https://guardaserie.clothing", + "guardaserieicu": "https://guardaserie.cfd", "hd4me": "https://hd4me.net", "ilcorsaronero": "https://ilcorsaronero.link", "ilgeniodellostreaming": "https://ilgeniodellostreaming.wtf", diff --git a/channels/0example.py.txt b/channels/0example.py.txt index e09fca3c..5c520f7d 100644 --- a/channels/0example.py.txt +++ b/channels/0example.py.txt @@ -118,7 +118,7 @@ def mainlist(item): # VOCE CHE APPARIRA' come prima voce nel menu di KOD! # [Voce Menu,['url','action','args',contentType] - top = [ '' ['', '', '', '']) + top = ([ '' ['', '', '', '']) # Se vuoi creare un menu personalizzato o perchè gli altri non # ti soddisfano diff --git a/channels/altadefinizioneclick.py b/channels/altadefinizioneclick.py index caee5416..83af45fa 100644 --- a/channels/altadefinizioneclick.py +++ b/channels/altadefinizioneclick.py @@ -50,7 +50,8 @@ def peliculas(item): patron = r'\s*
(?:\s*(?P[^<]+)<\/span>)?(?:\s*(?P[^<]+)<\/span>)?[^>]+>\s*[^"]+)"(?:(?:[^>]+>){5}\s*(?P[^<]+))?(?:[^>]+>){4}(?P[^<]+)' if not item.args: - patronBlock = r'(?:ULTIMI INSERITI|Serie TV)(?P<block>.*?)</section' + # patronBlock = r'(?:ULTIMI INSERITI|Serie TV)(?P<block>.*?)</section' + patronBlock = r'({})(?P<block>.*?)</section'.format('ULTIMI INSERITI' if item.contentType == 'movie' else 'Serie TV') patronNext = r'<a class="next page-numbers" href="([^"]+)">' @@ -58,7 +59,6 @@ def peliculas(item): @support.scrape def genres(item): - item.contentType = 'undefined' action = 'peliculas' patronGenreMenu = r'<li><a href="(?P<url>[^"]+)">(?P<title>[^<]+)<' @@ -122,6 +122,7 @@ def newest(categoria): def check(item): + item.contentType = 'tvshow' def get_season(pageData, seas_url, season): data = '' episodes = support.match(pageData if pageData else seas_url, patronBlock=patron_episode, patron=patron_option).matches diff --git a/channels/altadefinizionecommunity.py b/channels/altadefinizionecommunity.py index 86dd5e97..c53b9cc5 100644 --- a/channels/altadefinizionecommunity.py +++ b/channels/altadefinizionecommunity.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------ # Canale per Altadefinizione Community -from logging import debug -from core import jsontools, support + +from core import support from lib.fakeMail import Gmailnator from platformcode import config, platformtools, logger from core import scrapertools, httptools @@ -19,22 +19,22 @@ headers = {'Referer': host, 'x-requested-with': 'XMLHttpRequest'} @support.menu def mainlist(item): - support.info(item) + logger.debug(item) film = ['/load-more-film?anno=&order=&support_webp=1&type=movie&page=1', # Voce Menu,['url','action','args',contentType] - ('Generi', ['', 'genres', 'genres']), + ('Generi Film', ['', 'genres', 'genres']), ] tvshow = ['/load-more-film?type=tvshow&anno=&order=&support_webp=1&page=1', # Voce Menu,['url','action','args',contentType] - ('Generi', ['', 'genres', 'genres']), + ('Generi Serie TV', ['', 'genres', 'genres']), ] altri = [ - # ('Per Lettera', ['/lista-film', 'genres', 'letters']), + # ('A-Z', ['/lista-film', 'genres', 'letters']), ('Qualità', ['', 'genres', 'quality']), - # ('Anni', ['/anno', 'genres', 'years']) + ('Anni', ['/anno', 'genres', 'years']) ] search = '' @@ -130,7 +130,15 @@ def registerOrLogin(): @support.scrape def peliculas(item): json = {} - action = 'check' + + if item.contentType == 'undefined': + disabletmdb = True + action = 'check' + elif item.contentType == 'movie': + action = 'findvideos' + else: + action = 'episodios' + if '/load-more-film' not in item.url and '/search' not in item.url: # generi o altri menu, converto import ast ajax = support.match(item.url, patron='ajax_data\s*=\s*"?\s*([^;]+)', cloudscraper=True).match @@ -139,8 +147,8 @@ def peliculas(item): json = support.httptools.downloadpage(item.url, headers=headers, cloudscraper=True).json data = "\n".join(json['data']) else: - disabletmdb = True - data = support.httptools.downloadpage(item.url, headers=headers, cloudscraper=True).data + json = support.httptools.downloadpage(item.url, headers=headers, cloudscraper=True).json + data = "\n".join(json['data']) patron = r'wrapFilm">\s*<a href="(?P<url>[^"]+)">\s*<span class="year">(?P<year>[0-9]{4})</span>\s*<span[^>]+>[^<]+</span>\s*<span class="qual">(?P<quality>[^<]+).*?<img src="(?P<thumbnail>[^"]+)[^>]+>\s*<h3>(?P<title>[^<[]+)(?:\[(?P<lang>[sSuUbBiItTaA-]+))?' # paginazione @@ -156,7 +164,7 @@ def peliculas(item): def search(item, texto): - support.info("search ", texto) + logger.debug("search ", texto) item.args = 'search' item.url = host + "/search?s={}&page=1".format(texto) @@ -172,12 +180,21 @@ def search(item, texto): @support.scrape def genres(item): - support.info(item) + logger.debug(item) data = support.httptools.downloadpage(item.url, cloudscraper=True).data patronMenu = r'<a href="(?P<url>[^"]+)">(?P<title>[^<]+)' if item.args == 'quality': - patronBlock = 'Risoluzione(?P<block>.*?)</ul>' + item.contentType = 'undefined' + patronBlock = r'Risoluzione(?P<block>.*?)</ul>' + def itemlistHook(itemlist): + support.thumb(itemlist, mode='quality') + quality_list = ['4k','2k','hd','sd', '2k.md', 'hd.md', 'ts.md', 'cam'] + itemlist.sort(key=lambda it: quality_list.index(it.title.lower()) if it.title.lower() in quality_list else 99) + return itemlist + elif item.args == 'years': + item.contentType = 'undefined' + patronBlock = r'ANNO(?P<block>.*?</section>)' else: patronBlock = ('Film' if item.contentType == 'movie' else 'Serie TV') + r'<span></span></a>\s+<ul class="dropdown-menu(?P<block>.*?)active-parent-menu' action = 'peliculas' @@ -187,7 +204,7 @@ def genres(item): @support.scrape def episodios(item): - support.info(item) + logger.debug(item) data = item.data patron = r'class="playtvshow " data-href="(?P<url>[^"]+)' @@ -202,20 +219,18 @@ def episodios(item): def check(item): - if '/watch-unsubscribed' not in item.url: - playWindow = support.match(support.httptools.downloadpage(item.url, cloudscraper=True).data, patron='playWindow" href="([^"]+)') - video_url = playWindow.match - if '/tvshow' in video_url: - item.data = playWindow.data - item.contentType = 'tvshow' - return episodios(item) - else: - item.url = video_url.replace('/watch-unsubscribed', '/watch-external') - item.contentType = 'movie' - return findvideos(item) + resolve_url(item) + if '/tvshow' in item.url: + item.contentType = 'tvshow' + return episodios(item) + else: + item.contentType = 'movie' + return findvideos(item) + def findvideos(item): itemlist = [] + resolve_url(item) itemlist.append(item.clone(action='play', url=support.match(item.url, patron='allowfullscreen[^<]+src="([^"]+)"', cloudscraper=True).match, quality='')) @@ -231,3 +246,12 @@ def play(item): return [] else: return [item] + + +def resolve_url(item): + if '/watch-unsubscribed' not in item.url and '/watch-external' not in item.url: + playWindow = support.match(support.httptools.downloadpage(item.url, cloudscraper=True).data, patron='playWindow" href="([^"]+)') + video_url = playWindow.match + item.data = playWindow.data + item.url = video_url.replace('/watch-unsubscribed', '/watch-external') + return item diff --git a/channels/animesaturn.py b/channels/animesaturn.py index a9f7c569..1adeca52 100644 --- a/channels/animesaturn.py +++ b/channels/animesaturn.py @@ -92,7 +92,7 @@ def filter(item): matches = support.match(item.data if item.data else item.url, patron=r'<option value="(?P<value>[^"]+)"[^>]*>(?P<title>[^<]+)').matches for value, title in matches: itemlist.append(item.clone(title= support.typo(title,'bold'), url='{}{}&{}%5B0%5D={}'.format(host, item.args, item.parameter, value), action='peliculas', args='filter')) - support.thumb(itemlist, genre=True) + support.thumb(itemlist, mode='genre') return itemlist diff --git a/channels/animeunity.py b/channels/animeunity.py index bde40045..6b5af247 100644 --- a/channels/animeunity.py +++ b/channels/animeunity.py @@ -3,14 +3,18 @@ # Canale per AnimeUnity # ------------------------------------------------------------ -from lib.requests.sessions import session -import requests, json, copy, inspect -from core import support -from platformcode import autorenumber +import cloudscraper, json, copy, inspect +from core import jsontools, support, httptools, filetools +from platformcode import autorenumber, logger +import re +import xbmc + + +session = cloudscraper.create_scraper() host = support.config.get_channel_url() -response = support.httptools.downloadpage(host + '/archivio') -csrf_token = support.match(response.data, patron='name="csrf-token" content="([^"]+)"').match +response = session.get(host + '/archivio') +csrf_token = support.match(response.text, patron='name="csrf-token" content="([^"]+)"').match headers = {'content-type': 'application/json;charset=UTF-8', 'x-csrf-token': csrf_token, 'Cookie' : '; '.join([x.name + '=' + x.value for x in response.cookies])} @@ -119,7 +123,7 @@ def news(item): import cloudscraper session = cloudscraper.create_scraper() - fullJs = json.loads(support.match(session.get(item.url).text, headers=headers, patron=r'items-json="([^"]+)"', debug=True).match.replace('"','"')) + fullJs = json.loads(support.match(session.get(item.url).text, headers=headers, patron=r'items-json="([^"]+)"').match.replace('"','"')) js = fullJs['data'] for it in js: @@ -128,7 +132,7 @@ def news(item): fulltitle=it['anime']['title'], thumbnail=it['anime']['imageurl'], forcethumb = True, - video_url=it['link'], + video_url=it['scws_id'], plot=it['anime']['plot'], action='findvideos') ) @@ -150,9 +154,10 @@ def peliculas(item): item.args['order'] = order_list[order] payload = json.dumps(item.args) - records = requests.post(host + '/archivio/get-animes', headers=headers, data=payload).json()['records'] + records = session.post(host + '/archivio/get-animes', headers=headers, data=payload).json()['records'] for it in records: + logger.debug(jsontools.dump(it)) lang = support.match(it['title'], patron=r'\(([It][Tt][Aa])\)').match title = support.re.sub(r'\s*\([^\)]+\)', '', it['title']) @@ -171,14 +176,14 @@ def peliculas(item): itm.fulltitle = itm.show = itm.contentTitle = title itm.contentSerieName = '' itm.action = 'findvideos' - itm.video_url = it['episodes'][0]['link'] + itm.video_url = it['episodes'][0]['scws_id'] else: itm.contentType = 'tvshow' itm.contentTitle = '' itm.fulltitle = itm.show = itm.contentSerieName = title itm.action = 'episodios' - itm.episodes = it['episodes'] if 'episodes' in it else it['link'] + itm.episodes = it['episodes'] if 'episodes' in it else it['scws_id'] itm.video_url = item.url itemlist.append(itm) @@ -205,7 +210,7 @@ def episodios(item): plot=item.plot, action='findvideos', contentType='episode', - video_url=it['link'])) + video_url=it['scws_id'])) if inspect.stack()[1][3] not in ['find_episodes']: autorenumber.start(itemlist, item) @@ -215,8 +220,67 @@ def episodios(item): def findvideos(item): - support.info() - if not 'vvvvid' in item.video_url: - return support.server(item,itemlist=[item.clone(title=support.config.get_localized_string(30137), url=item.video_url, server='directo', action='play')]) + # def calculateToken(): + # from time import time + # from base64 import b64encode as b64 + # import hashlib + # o = 48 + # n = support.match('https://au-1.scws-content.net/get-ip').data + # i = 'Yc8U6r8KjAKAepEA' + # t = int(time() + (3600 * o)) + # l = '{}{} {}'.format(t, n, i) + # md5 = hashlib.md5(l.encode()) + # s = '?token={}&expires={}'.format(b64(md5.digest()).decode().replace('=', '').replace('+', "-").replace('\\', "_"), t) + # return s + # token = calculateToken() + + # url = 'https://streamingcommunityws.com/master/{}{}'.format(item.video_url, token) + + # # support.dbg() + + # m3u8_original = httptools.downloadpage(url, CF=False).data + + # m_video = re.search(r'\.\/video\/(\d+p)\/playlist.m3u8', m3u8_original) + # video_res = m_video.group(1) + # m_audio = re.search(r'\.\/audio\/(\d+k)\/playlist.m3u8', m3u8_original) + # audio_res = m_audio.group(1) + + # # https://streamingcommunityws.com/master/5957?type=video&rendition=480p&token=wQLowWskEnbLfOfXXWWPGA&expires=1623437317 + # video_url = 'https://streamingcommunityws.com/master/{}{}&type=video&rendition={}'.format(item.video_url, token, video_res) + # audio_url = 'https://streamingcommunityws.com/master/{}{}&type=audio&rendition={}'.format(item.video_url, token, audio_res) + + # m3u8_original = m3u8_original.replace( m_video.group(0), video_url ) + # m3u8_original = m3u8_original.replace( m_audio.group(0), audio_url ) + + # file_path = 'special://temp/animeunity.m3u8' + + # filetools.write(xbmc.translatePath(file_path), m3u8_original, 'w') + + # return support.server(item, itemlist=[item.clone(title=support.config.get_localized_string(30137), url=file_path, manifest = 'hls', server='directo', action='play')]) + # item.url=item.video_url + + directLink = False + if item.video_url == None: + if item.extra == "tvshow": + epnum = item.episode + logger.info('it is a episode', epnum) + episode = None + for ep in item.episodes: + if ep["number"] == epnum: + episode = ep + break + if episode == None: + logger.warn('cannot found episode') + else: + item.url = episode["link"] + directLink = True + + if directLink: + logger.info('try direct link') + return support.server(item, itemlist=[item.clone(title=support.config.get_localized_string(30137), url=item.url, server='directo', action='play')]) else: - return support.server(item, item.video_url) \ No newline at end of file + return support.server(item, itemlist=[item.clone(title="StreamingCommunityWS", url=str(item.video_url), manifest = 'hls', server='streamingcommunityws', action='play')]) + + + + diff --git a/channels/aniplay.py b/channels/aniplay.py index 8d522504..dd43e9dc 100644 --- a/channels/aniplay.py +++ b/channels/aniplay.py @@ -26,13 +26,12 @@ def mainlist(item): def submenu_az(item): itemlist = [] - if item.args == 'az': - for letter in ['0-9'] + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): - itemlist.append(item.clone(title = support.typo(letter, 'bold'), - url= host + '/api/anime/find-by-char', - action= 'peliculas', - variable= '&character=' + letter, - thumbnail=support.thumb('az'))) + for letter in ['0-9'] + list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'): + itemlist.append(item.clone(title = support.typo(letter, 'bold'), + url= host + '/api/anime/find-by-char', + action= 'peliculas', + variable= '&character=' + letter, + thumbnail=support.thumb('az'))) return itemlist def submenu_year(item): diff --git a/channels/casacinema.py b/channels/casacinema.py index 4e38b523..e3d3a486 100644 --- a/channels/casacinema.py +++ b/channels/casacinema.py @@ -106,7 +106,8 @@ def peliculas(item): if item.args == 'newest': patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div>\s*?<div[^>]+>(?P<title>[^\(\[<]+)(?:\[(?P<quality1>HD)\])?[ ]?(?:\(|\[)?(?P<lang>[sS]ub-[iI][tT][aA])?(?:\)|\])?[ ]?(?:\[(?P<quality>.+?)\])?[ ]?(?:\((?P<year>\d+)\))?<(?:[^>]+>.+?(?:title="Nuovi episodi">(?P<episode>\d+x\d+)[ ]?(?P<lang2>Sub-Ita)?|title="IMDb">(?P<rating>[^<]+)))?' else: - patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div>\s*?<div[^>]+>(?P<title>[^\(\[<]+)(?:\[(?P<quality1>HD)\])?\s?(?:[\(\[])?(?P<lang>[sS]ub-[iI][tT][aA])?(?:[\)\]])?\s?(?:\[(?P<quality>.+?)\])?\s?(?:\((?P<year>\d+)\))?<' + # patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div>\s*?<div[^>]+>(?P<title>[^\(\[<]+)(?:\[(?P<quality1>HD)\])?\s?(?:[\(\[])?(?P<lang>[sS]ub-[iI][tT][aA])?(?:[\)\]])?\s?(?:\[(?P<quality>.+?)\])?\s?(?:\((?P<year>\d+)\))?<' + patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div>\s*?<div[^>]+>(?P<title>[^\(\[<]+)(?P<title2>\([\D*]+\))?(?:\[(?P<quality1>HD)\])?\s?(?:[\(\[])?(?P<lang>[sS]ub-[iI][tT][aA])?(?:[\)\]])?\s?(?:\[(?P<quality>.+?)\])?\s?(?:\((?P<year>\d+)\))?(?:\(\D{2}\s\d{4}\))?<' patronNext = r'<a href="([^"]+)"\s*>Pagina' # debug = True diff --git a/channels/cineblog01.py b/channels/cineblog01.py index 6bcb72ea..4610b144 100644 --- a/channels/cineblog01.py +++ b/channels/cineblog01.py @@ -93,13 +93,14 @@ def search(item, text): @support.scrape def peliculas(item): + # debug = True # esclusione degli articoli 'di servizio' - curYear = datetime.date.today().year - blacklist = ['BENVENUTI', 'Richieste Serie TV', 'CB01.UNO ▶ TROVA L’INDIRIZZO UFFICIALE ', - 'Aggiornamento Quotidiano Serie TV', - 'Openload: la situazione. Benvenuto Verystream', 'Openload: lo volete ancora?', - 'OSCAR ' + str(curYear) + ' ▶ VOTA IL TUO FILM PREFERITO! 🎬', - 'Auguri di Buon Natale e Felice Anno Nuovo! – ' + str(curYear) + '!'] + # curYear = datetime.date.today().year + # blacklist = ['BENVENUTI', 'Richieste Serie TV', 'CB01.UNO ▶ TROVA L’INDIRIZZO UFFICIALE ', + # 'Aggiornamento Quotidiano Serie TV', 'AVVISO!!!', + # 'Openload: la situazione. Benvenuto Verystream', 'Openload: lo volete ancora?', + # 'OSCAR ' + str(curYear) + ' ▶ VOTA IL TUO FILM PREFERITO! 🎬', + # 'Auguri di Buon Natale e Felice Anno Nuovo! – ' + str(curYear) + '!'] if 'newest' in item.args: pagination = '' @@ -112,11 +113,11 @@ def peliculas(item): action = 'episodios' elif '/serietv/' not in item.url: - patron = r'<div class="card-image">\s*<a[^>]+>\s*<img src="(?P<thumb>[^" ]+)" alt[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+><a href="?(?P<url>[^" >]+)(?:\/|"|\s+)>(?P<title>[^<[(]+)(?:\[(?P<quality>[a-zA-Z/]+)\]\s*)?(?:\[(?P<lang>Sub-ITA|ITA)\]\s*)?(?:\[(?P<quality2>[a-zA-Z/]+)\]\s*)? (?:\((?P<year>[0-9]{4})\))?[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<genre>[^<>&‖“]+)(?:[^ ]+\s*DURATA\s*(?P<duration>[0-9]+)[^>]+>[^>]+>[^>]+>(?P<plot>[^<>]+))?' + patron = r'(?<!sticky )hentry.*?<div class="card-image">\s*<a[^>]+>\s*<img src="(?P<thumb>[^" ]+)" alt[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+><a href="?(?P<url>[^" >]+)(?:\/|"|\s+)>(?P<title>[^<[(]+)(?:\[(?P<quality>[a-zA-Z/]+)\]\s*)?(?:\[(?P<lang>Sub-ITA|ITA)\]\s*)?(?:\[(?P<quality2>[a-zA-Z/]+)\]\s*)? (?:\((?P<year>[0-9]{4})\))?[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<genre>[^<>&‖“]+)(?:[^ ]+\s*DURATA\s*(?P<duration>[0-9]+)[^>]+>[^>]+>[^>]+>(?P<plot>[^<>]+))?' action = 'findvideos' else: - patron = r'card-image[^>]*>\s*<a href=(?:")?(?P<url>[^" >]+)(?:")?\s*>\s*<img src=(?:")?(?P<thumb>[^" ]+)(?:")? alt="(?P<title>.*?)(?: – \d+×\d+)?(?:"| – )(?:(?P<lang>Sub-ITA|ITA))?[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>(?P<genre>[^\(]+)\((?P<year>\d{4})[^>]*>[^>]+>[^>]+>[^>]+>(?:<p>)?(?P<plot>[^<]+)' + patron = r'(?<!sticky )hentry.*?card-image[^>]*>\s*<a href=(?:")?(?P<url>[^" >]+)(?:")?\s*>\s*<img src=(?:")?(?P<thumb>[^" ]+)(?:")? alt="(?P<title>.*?)(?: – \d+×\d+)?(?:"| – )(?:(?P<lang>Sub-ITA|ITA))?[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>[^>]+>[^>]+>[^>]*>(?P<genre>[^\(]+)\((?P<year>\d{4})[^>]*>[^>]+>[^>]+>[^>]+>(?:<p>)?(?P<plot>[^<]+)' action = 'episodios' item.contentType = 'tvshow' @@ -136,17 +137,17 @@ def episodios(item): @support.scrape def folder(item, data): """ - Quando c'è un link ad una cartelle di vcrypt contenente più stagioni + Quando c'è un link ad una cartella contenente più stagioni """ actLike = 'episodios' addVideolibrary = False downloadEnabled = False - folderUrl = scrapertools.find_single_match(data, r'TUTTA L[EA] \w+\s+(?:–|-)\s+<a href="?([^" ]+)').replace( - '.net/', '.pw/') # vcrypt.pw non ha CF + folderUrl = scrapertools.find_single_match(data, r'TUTTA L[EA] \w+\s+(?:–|-)\s+<a href="?([^" ]+)') data = httptools.downloadpage(folderUrl, disable_directIP=True).data - patron = r'><a href="(?P<url>[^"]+)[^>]+>(?P<title>[^<]+)' + patron = r'<td>(?P<title>[^<]+)<td><a [^>]+href="(?P<url>[^"]+)[^>]+>' sceneTitle = True + # debug = True def itemHook(item): item.serieFolder = True diff --git a/channels/discoveryplus.py b/channels/discoveryplus.py index 9f735cd9..491c1695 100644 --- a/channels/discoveryplus.py +++ b/channels/discoveryplus.py @@ -35,7 +35,9 @@ def mainlist(item): def liveDict(): livedict = {} - for key in session.get(api + '/cms/routes/home?decorators=viewingHistory&include=default', headers=headers).json()['included']: + + for key in session.get(api + '/cms/routes/canali?decorators=viewingHistory&include=default', headers=headers).json()['included']: + if key['type'] == 'channel' and key.get('attributes',{}).get('hasLiveStream', '') and 'Free' in key.get('attributes',{}).get('packages', []): title = key['attributes']['name'] livedict[title] = {} @@ -64,7 +66,7 @@ def live(item): itemlist =[] for name, values in liveDict().items(): itemlist.append(item.clone(title=typo(name,'bold'), fulltitle=name, plot=values['plot'], url=values['url'], id=values['id'], action='play', forcethumb=True, no_return=True)) - return support.thumb(itemlist, live=True) + return support.thumb(itemlist, mode='live') def genres(item): @@ -182,7 +184,7 @@ def play(item): item.fulltitle = item.livefilter item.forcethumb = True item.no_return = True - support.thumb(item, live=True) + support.thumb(item, mode='live') if item.contentType == 'episode': data = session.get('{}/playback/v2/videoPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{}) else: data = session.get('{}/playback/v2/channelPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{}) if data.get('protection', {}).get('drm_enabled',True): diff --git a/channels/dsda.json b/channels/dsda.json index 4ec18a80..9ae3060f 100644 --- a/channels/dsda.json +++ b/channels/dsda.json @@ -2,7 +2,7 @@ "id": "dsda", "name": "D.S.D.A", "language": ["ita"], - "active": true, + "active": false, "thumbnail": "dsda.png", "banner": "dsda.png", "categories": ["documentary"], diff --git a/channels/eurostreaming.py b/channels/eurostreaming.py index f4ec0f92..b67a33e9 100644 --- a/channels/eurostreaming.py +++ b/channels/eurostreaming.py @@ -31,9 +31,10 @@ def mainlist(item): def peliculas(item): # debug = True action = 'episodios' + if item.args == 'newest': item.contentType = 'episode' - patron = r'<span class="serieTitle" style="font-size:20px">(?P<title>[^<]+) –\s*<a href="(?P<url>[^"]+)"[^>]*>\s?(?P<episode>\d+[×x]\d+-\d+|\d+[×x]\d+) (?P<title2>[^<\(]+)\s?\(?(?P<lang>SUB ITA)?\)?</a>' + patron = r'<span class="serieTitle" style="font-size:20px">(?P<title>[^<]+) –\s*<a href="(?P<url>[^"]+)"[^>]*>\s+?(?P<episode>\d+[×x]\d+-\d+|\d+[×x]\d+) (?P<title2>[^<\(]+)\s?\(?(?P<lang>SUB ITA)?\)?</a>' pagination = '' else: patron = r'<div class="post-thumb">.*?<img src="(?P<thumb>[^"]+)".*?><a href="(?P<url>[^"]+)"[^>]+>(?P<title>.+?)\s?(?: Serie Tv)?\s?\(?(?P<year>\d{4})?\)?<\/a><\/h2>' diff --git a/channels/filmpertutti.py b/channels/filmpertutti.py index e1734273..9d9cefd6 100644 --- a/channels/filmpertutti.py +++ b/channels/filmpertutti.py @@ -39,7 +39,7 @@ def peliculas(item): patronNext = r'<a href="([^"]+)[^>]+>Pagina' else: patronBlock = r'<ul class="posts">(?P<block>.*)<div class="clear[^"]*">' - patron = r'<li>\s?<a href="(?P<url>[^"]+)" data-thumbnail="(?P<thumb>[^"]+)">.*?<div class="title[^"]*">(?P<title>.+?)(?:\s\[(?P<quality>HD)\])?<\/div><div class="episode[^"]*"[^>]+>(?P<episode>[^<(]+)(?:\((?P<lang>[a-zA-Z\-]+)\))?' + patron = r'<li>\s?<a href="(?P<url>[^"]+)" data-thumbnail="(?P<thumb>[^"]+)">.*?<div class="title[^"]*">(?P<title>.+?)(?:\s\[(?P<quality>HD)\])?<\/div>\s*<div class="episode[^"]*"[^>]+>(?P<episode>[^<(]+)(?:\((?P<lang>[a-zA-Z\-]+)\))?' if item.args == 'search': action = 'check' diff --git a/channels/guardaserieclick.py b/channels/guardaserieclick.py index 008a7eac..ac1cdace 100644 --- a/channels/guardaserieclick.py +++ b/channels/guardaserieclick.py @@ -25,18 +25,16 @@ headers = [['Referer', host]] @support.menu def mainlist(item): - - tvshow = ['/lista-serie-tv', - ('Aggiornamenti', ['/lista-serie-tv', 'peliculas', 'update']), - ('Generi', ['/categorie', 'genres', 'genres']), - ('News Sub-ITA', ['/lista-serie-tv', 'peliculas', 'ined']), - ('Da non perdere', ['/lista-serie-tv', 'peliculas', 'nolost']), - ('Classiche', ["/lista-serie-tv", 'peliculas', 'classic']), - ('Anime/Cartoni', ["/category/animazione/", 'peliculas', 'genres']) - ] + tvshow = ['', + ('Aggiornamenti', ['', 'peliculas', 'update']), + ('Generi', ['', 'genres', 'genres']), + ('News Sub-ITA', ['', 'peliculas', 'ined']), + ('Anime/Cartoni', ["/category/animazione/", 'peliculas', 'genres']) + ] return locals() + ##@support.scrape ##def peliculas(item): #### import web_pdb; web_pdb.set_trace() @@ -76,7 +74,7 @@ def mainlist(item): @support.scrape def peliculas(item): -## import web_pdb; web_pdb.set_trace() + ## import web_pdb; web_pdb.set_trace() info('peliculas ->\n', item) action = 'episodios' @@ -87,36 +85,36 @@ def peliculas(item): patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)</p>' patronNext = r'rel="next" href="([^"]+)">' item.contentType = 'tvshow' -## elif item.args == 'search': -## patronBlock = r'<h2 style="color:\s?white !important.?" class="title-typology">(?P<block>.*?)<div class="container-fluid whitebg" style="">' -## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)</p>' + ## elif item.args == 'search': + ## patronBlock = r'<h2 style="color:\s?white !important.?" class="title-typology">(?P<block>.*?)<div class="container-fluid whitebg" style="">' + ## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)</p>' else: end_block = r'(?P<block>.*?)<div\s+class="btn btn-lg btn-default btn-load-other-series">' patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' pagination = 25 if item.args == 'ined': deflang = 'SUB-ITA' - patronBlock = r'<span\s+class="label label-default label-title-typology">'+end_block -## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' -## pagination = 25 + patronBlock = r'<span\s+class="label label-default label-title-typology">' + end_block + ## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' + ## pagination = 25 elif item.args == 'update': - patronBlock = r'<div\s+class="container-fluid greybg title-serie-lastep title-last-ep fixed-title-wrapper containerBottomBarTitle">'+end_block - patron = r'<a(?: rel="[^"]+")? href="(?P<url>[^"]+)"(?: class="[^"]+")?>[ ]<img class="[^"]+"[ ]title="[^"]+"[ ]alt="[^"]+"[ ](?:|meta-)?src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?:\d+.\d+)[ ]\((?P<lang>[a-zA-Z\-]+)[^<]+<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)<' - elif item.args == 'nolost': - patronBlock = r'<h2 class="title-typology styck-top" meta-class="title-serie-danonperd">'+end_block -## pagination = 25 - elif item.args == 'classic': - patronBlock = r'<h2 class="title-typology styck-top" meta-class="title-serie-classiche">'+end_block -## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' -## pagination = 25 -## elif item.args == 'anime': -## + patronBlock = r'<div\s+class="container-fluid greybg title-serie-lastep title-last-ep fixed-title-wrapper containerBottomBarTitle">' + end_block + patron = r'href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>.+?class="strongText">(?P<title>.+?)<' + # elif item.args == 'nolost': + # patronBlock = r'<h2 class="title-typology styck-top" meta-class="title-serie-danonperd">' + end_block + # pagination = 25 + # elif item.args == 'classic': + # patronBlock = r'<h2 class="title-typology styck-top" meta-class="title-serie-classiche">' + end_block + ## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' + ## pagination = 25 + ## elif item.args == 'anime': + ## else: - patronBlock = r'<div\s+class="container container-title-serie-new container-scheda" meta-slug="new">'+end_block -## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' -## pagination = 25 - #support.regexDbg(item, patronBlock, headers) - #debug = True + patronBlock = r'<div\s+class="container container-title-serie-new container-scheda" meta-slug="new">' + end_block + ## patron = r'<a href="(?P<url>[^"]+)".*?>\s<img\s.*?src="(?P<thumb>[^"]+)"\s/>[^>]+>[^>]+>\s[^>]+>\s(?P<year>\d{4})?\s.+?class="strongText">(?P<title>.+?)<' + ## pagination = 25 + # support.regexDbg(item, patronBlock, headers) + # debug = True return locals() @@ -129,21 +127,21 @@ def episodios(item): patronBlock = r'<h2 class="title-typology">Episodi (?P<stagione>\d+).{1,3}Stagione</h2>(?P<block>.*?)<div class="container">' def itemHook(item): - item.title = item.title.replace(item.fulltitle, '').replace('-','',1) + item.title = item.title.replace(item.fulltitle, '').replace('-', '', 1) return item - #debug = True + # debug = True return locals() + @support.scrape def genres(item): info() action = 'peliculas' - patronGenreMenu = r'<li>\s<a\shref="(?P<url>[^"]+)"[^>]+>(?P<title>[^<]+)</a></li>' + patronMenu = r'<li>\s<a\shref="(?P<url>[^"]+)"[^>]+>(?P<title>[^<]+)</a></li>' patron_block = r'<ul\sclass="dropdown-menu category">(?P<block>.*?)</ul>' - item.contentType = '' - + # debug = True return locals() @@ -161,15 +159,16 @@ def search(item, text): info("%s" % line) return [] + def newest(categoria): info() itemlist = [] item = Item() - item.contentType= 'tvshow' + item.contentType = 'tvshow' item.args = 'update' try: if categoria == "series": - item.url = "%s/lista-serie-tv" % host + item.url = host item.action = "peliculas" itemlist = peliculas(item) diff --git a/channels/ilgeniodellostreaming.py b/channels/ilgeniodellostreaming.py index 2342f9c8..c17e962d 100644 --- a/channels/ilgeniodellostreaming.py +++ b/channels/ilgeniodellostreaming.py @@ -105,6 +105,7 @@ def episodios(item): # debugBlock = True return locals() + @support.scrape def genres(item): info(item) @@ -118,15 +119,17 @@ def genres(item): elif item.args == 'letter': patronBlock = r'<div class="movies-letter">(?P<block>.*?)<div class="clearfix">' - patronGenreMenu = r'<a(?:.+?)?href="(?P<url>.*?)"[ ]?>(?P<title>.*?)<\/a>' + patronMenu = r'<a(?:.+?)?href="(?P<url>.*?)"[ ]?>(?P<title>.*?)<\/a>' + # debugBlock = True return locals() + def search(item, text): info(text) - itemlist = [] + import uuid text = text.replace(' ', '+') - item.url = host + '/?a=b&s=' + text + item.url = host + '/?' + uuid.uuid4().hex + '=' + uuid.uuid4().hex + '&s=' + text try: item.args = 'search' return peliculas(item) diff --git a/channels/ilgeniodellostreaming_cam.json b/channels/ilgeniodellostreaming_cam.json index f51f9627..78746f9b 100644 --- a/channels/ilgeniodellostreaming_cam.json +++ b/channels/ilgeniodellostreaming_cam.json @@ -1,7 +1,7 @@ { "id": "ilgeniodellostreaming_cam", "name": "IlGenioDelloStreaming CAM", - "active": true, + "active": false, "language": ["ita"], "thumbnail": "ilgeniodellostreaming.png", "banner": "ilgeniodellostreaming.png", diff --git a/channels/la7.py b/channels/la7.py index 857159a4..e45ca172 100644 --- a/channels/la7.py +++ b/channels/la7.py @@ -36,13 +36,13 @@ def mainlist(item): def live(item): itemlist = [item.clone(title=support.typo('La7', 'bold'), fulltitle='La7', url= host + '/dirette-tv', action='play', forcethumb = True, no_return=True), item.clone(title=support.typo('La7d', 'bold'), fulltitle='La7d', url= host + '/live-la7d', action='play', forcethumb = True, no_return=True)] - return support.thumb(itemlist, live=True) + return support.thumb(itemlist, mode='live') def replay_channels(item): itemlist = [item.clone(title=support.typo('La7', 'bold'), fulltitle='La7', url= host + '/rivedila7/0/la7', action='replay_menu', forcethumb = True), item.clone(title=support.typo('La7d', 'bold'), fulltitle='La7d', url= host + '/rivedila7/0/la7d', action='replay_menu', forcethumb = True)] - return support.thumb(itemlist, live=True) + return support.thumb(itemlist, mode='live') @support.scrape @@ -84,6 +84,8 @@ def search(item, text): def peliculas(item): search = item.search disabletmdb = True + addVideolibrary = False + downloadEnabled = False action = 'episodios' patron = r'<a href="(?P<url>[^"]+)"[^>]+><div class="[^"]+" data-background-image="(?P<t>[^"]+)"></div><div class="titolo">\s*(?P<title>[^<]+)<' def itemHook(item): @@ -96,7 +98,7 @@ def peliculas(item): @support.scrape def episodios(item): data = support.match(item).data - debug = True + # debug = True action = 'play' if '>puntate<' in data: patronBlock = r'>puntate<(?P<block>.*?)home-block-outbrain' @@ -109,6 +111,7 @@ def episodios(item): patron = r'(?:<a href="(?P<url>[^"]+)">[^>]+><div class="[^"]+" data-background-image="(?P<t>[^"]*)">[^>]+>[^>]+>[^>]+>(?:[^>]+>)?(?:[^>]+>){6}?)\s*(?P<title>[^<]+)<(?:[^>]+>[^>]+>[^>]+><div class="data">(?P<date>[^<]+))?|class="heading">[^>]+>(?P<Title>[^<]+).*?window.shareUrl = "(?P<Url>[^"]+)".*?poster:\s*"(?P<Thumb>[^"]+)", title: "(?P<desc>[^"]+)"' patronNext = r'<a href="([^"]+)">›' addVideolibrary = False + downloadEnabled = False def itemHook(item): if item.Thumb: item.t = item.Thumb diff --git a/channels/mediasetplay.json b/channels/mediasetplay.json index 660a0a7b..e92fc4e5 100644 --- a/channels/mediasetplay.json +++ b/channels/mediasetplay.json @@ -8,6 +8,23 @@ "categories": ["movie", "tvshow", "documentary", "live"], "not_active": ["include_in_newest"], "default_off": ["include_in_global_search"], - "settings": [], - "cloudflare": true + "settings": [ + { + "id": "mpd", + "type": "bool", + "label": "Preferisci mpd", + "default": true, + "enabled": true, + "visible": true + }, + { + "id": "pagination", + "type": "list", + "label": "Pagination", + "default": 1, + "enabled": true, + "visible": true, + "lvalues": ["10", "20", "30", "40", "50", "60", "70", "80", "90", "100"] + } + ] } diff --git a/channels/mediasetplay.py b/channels/mediasetplay.py index 1ee3c480..4b2d7a50 100644 --- a/channels/mediasetplay.py +++ b/channels/mediasetplay.py @@ -2,359 +2,332 @@ # ------------------------------------------------------------ # Canale per Mediaset Play # ------------------------------------------------------------ -from platformcode import logger -import uuid + +from platformcode import logger, config +import uuid, datetime, xbmc import requests, sys from core import support -if sys.version_info[0] >= 3: from urllib.parse import urlencode, quote -else: from urllib import urlencode, quote -if sys.version_info[0] >= 3: from concurrent import futures -else: from concurrent_py2 import futures -from collections import OrderedDict +if sys.version_info[0] >= 3: + from urllib.parse import urlencode, quote +else: + from urllib import urlencode, quote -PAGINATION = 4 +host = 'https://www.mediasetplay.mediaset.it' +loginUrl = 'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0' -host = '' -post_url = '?assetTypes=HD,browser,widevine,geoIT|geoNo:HD,browser,geoIT|geoNo:HD,geoIT|geoNo:SD,browser,widevine,geoIT|geoNo:SD,browser,geoIT|geoNo:SD,geoIT|geoNo&auto=true&balance=true&format=smil&formats=MPEG-DASH,MPEG4,M3U&tracking=true' -deviceid = '61d27df7-5cbf-4419-ba06-cfd27ecd4588' -loginUrl = 'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v1.0' -loginData = {"cid": deviceid, "platform": "pc", "appName": "web/mediasetplay-web/d667681"} -lic_url = 'https://widevine.entitlement.theplatform.eu/wv/web/ModularDrm/getRawWidevineLicense?releasePid=%s&account=http://access.auth.theplatform.com/data/Account/2702976343&schema=1.0&token={token}|Accept=*/*&Content-Type=&User-Agent=' + support.httptools.get_user_agent() + '|R{{SSM}}|' -entry = 'https://api.one.accedo.tv/content/entry/{id}?locale=it' -entries = 'https://api.one.accedo.tv/content/entries?id={id}&locale=it' +clientid = 'f66e2a01-c619-4e53-8e7c-4761449dd8ee' + + +loginData = {"client_id": clientid, "platform": "pc", "appName": "web//mediasetplay-web/5.1.493-plus-da8885b"} sessionUrl = "https://api.one.accedo.tv/session?appKey=59ad346f1de1c4000dfd09c5&uuid={uuid}&gid=default" -current_session = requests.Session() -current_session.headers.update({'Content-Type': 'application/json', 'User-Agent': support.httptools.get_user_agent(), 'Referer': support.config.get_channel_url()}) +session = requests.Session() +session.headers.update({'Content-Type': 'application/json', 'User-Agent': support.httptools.get_user_agent(), 'Referer': host}) + +entry = 'https://api.one.accedo.tv/content/entry/{id}?locale=it' +entries = 'https://api.one.accedo.tv/content/entries?id={id}&locale=it' # login anonimo -res = current_session.post(loginUrl, json=loginData, verify=False) -Token = res.headers['t-cts'] -current_session.headers.update({'t-apigw': res.headers['t-apigw'], 't-cts': Token}) -lic_url = lic_url.format(token=Token) -tracecid = res.json()['response']['traceCid'] -cwid = res.json()['response']['cwId'] +res = session.post(loginUrl, json=loginData, verify=False) +Token = res.json()['response']['beToken'] +sid = res.json()['response']['sid'] +session.headers.update({'authorization': 'Bearer ' + Token}) # sessione -res = current_session.get(sessionUrl.format(uuid=str(uuid.uuid4())), verify=False) -current_session.headers.update({'x-session': res.json()['sessionKey']}) +sessionKey = session.get(sessionUrl.format(uuid=str(uuid.uuid4())), verify=False).json()['sessionKey'] +session.headers.update({'x-session': sessionKey}) -cdict = {'CWFILMTOPVIEWED':'filmPiuVisti24H', - 'CWFILMCOMEDY':'filmCommedia', - 'CWFILMACTION':'filmAzioneThrillerAvventura', - 'CWFILMDRAMATIC':'filmDrammatico', - 'CWFILMSENTIMENTAL':'filmSentimentale', - 'CWFILMCLASSIC':'filmClassici', - 'personToContentFilm':'personToContentFilm', - 'CWHOMEFICTIONNOWELITE':'stagioniFictionSerieTvSezione', - 'CWFICTIONSOAP':'mostRecentSoapOpera', - 'CWFICTIONDRAMATIC':'stagioniFictionDrammatico', - 'CWFICTIONPOLICE':'stagioniFictionPoliziesco', - 'CWFICTIONCOMEDY':'stagioniFictionCommedia', - 'CWFICTIONSITCOM':'stagioniFictionSitCom', - 'CWFICTIONSENTIMENTAL':'stagioniFictionSentimentale', - 'CWFICTIONBIOGRAPHICAL':'stagioniFictionBiografico', - 'CWPROGTVPRIME':'stagioniPrimaSerata', - 'CWPROGTVDAY':'stagioniDaytime', - 'CWPROGTVTOPVIEWED':'programmiTvClip24H', - 'CWPROGTVTALENT':'stagioniReality', - 'CWPROGTVVARIETY':'stagioniVarieta', - 'CWPROGTVTALK':'stagioniTalk', - 'CWPROGTVTG':'mostRecentTg', - 'CWPROGTVSPORT':'mostRecentSport', - 'CWPROGTVMAGAZINE':'stagioniCucinaLifestyle', - 'CWDOCUMOSTRECENT':'mostRecentDocumentariFep', - 'CWDOCUTOPVIEWED':'stagioniDocumentari', - 'CWDOCUSPAZIO':'documentariSpazio', - 'CWDOCUNATURANIMALI':'documentariNatura', - 'CWDOCUSCIENZATECH':'documentariScienza', - 'CWDOCUBIOSTORIE':'documentariBioStoria', - 'CWDOCUINCHIESTE':'documentariInchiesta', - 'CWFILMDOCU':'filmDocumentario', - 'CWKIDSBOINGFORYOU':'kidsBoing', - 'CWKIDSCARTOONITO':'kidsCartoonito', - 'CWKIDSMEDIASETBRAND':'kidsMediaset', - 'CWENABLERKIDS':'stagioniKids'} +pagination = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100][config.get_setting('pagination', 'mediasetplay')] @support.menu def mainlist(item): - top = [('Dirette {bold}', ['https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-stations?sort=ShortTitle', 'live'])] + top = [('Dirette {bold}', ['', 'live'])] - menu = [('Film {bullet bold}', ['5acfcbc423eec6000d64a6bb', 'menu', ['Tutti','all','searchMovie']]), - ('Fiction / Serie TV {bullet bold}', ['5acfcb3c23eec6000d64a6a4', 'menu', ['Tutte','all','searchStagioni'], 'tvshow']), - ('Programmi TV{ bullet bold}', ['5acfc8011de1c4000b6ec953', 'menu', ['Tutti','all','searchStagioni'], 'tvshow']), - ('Documentari {bullet bold}', ['5bfd17c423eec6001aec49f9', 'menu', ['Tutti','all',''], 'undefined']), - ('Kids {bullet bold}', ['5acfcb8323eec6000d64a6b3', 'menu',['Tutti','all',''], 'undefined']), - ('Family {bullet bold}', ['5e662d01a0e845001d56875b', 'menu',['Tutti','all',''], 'undefined']), - ] + menu = [('Film {bullet bold}', ['/cinema', 'peliculas', {'uxReference':'filmUltimiArrivi'}, 'movie']), + ('Fiction / Serie TV {bullet bold}', ['/fiction', 'menu', '5acfcb3c23eec6000d64a6a4', 'tvshow']), + ('Programmi TV{ bullet bold}', ['/programmitv', 'menu', '5acfc8011de1c4000b6ec953', 'tvshow']), + ('Documentari {bullet bold}', ['/documentari', 'menu', '5bfd17c423eec6001aec49f9', 'undefined']), + ('Kids {bullet bold}', ['/kids', 'menu', '5acfcb8323eec6000d64a6b3', 'undefined'])] search = '' return locals() +def menu(item): + logger.debug() + itemlist = [] + res = get_from_id(item) + for it in res: + if 'uxReference' in it: + itemlist.append(item.clone(title=support.typo(it['title'], 'bullet bold'), + url= it['landingUrl'], + args={'uxReference':it.get('uxReferenceV2', ''), 'params':it.get('uxReferenceV2Params', ''), 'feed':it.get('feedurlV2','')}, + action='peliculas')) + return itemlist + + +def live(item): + itemlist = [] + + res = session.get('https://static3.mediasetplay.mediaset.it/apigw/nownext/nownext.json').json()['response'] + allguide = res['listings'] + stations = res['stations'] + + for it in stations.values(): + plot = '' + title = it['title'] + url = 'https:' + it['mediasetstation$pageUrl'] + if 'plus' in title.lower() or 'premium' in title.lower(): continue + if it['callSign'] in allguide: + + guide = allguide[it['callSign']] + plot = '[B]{}[/B]\n{}\n\nA Seguire:\n[B]{}[/B]\n{}'.format(guide['currentListing']['mediasetlisting$epgTitle'], + guide['currentListing']['description'], + guide['nextListing']['mediasetlisting$epgTitle'], + guide['nextListing']['description'],) + + itemlist.append(item.clone(title=support.typo(title, 'bold'), fulltitle=title, callSign=it['callSign'], urls=guide['tuningInstruction']['urn:theplatform:tv:location:any'], plot=plot, url=url, action='play', forcethumb=True)) + + itemlist.sort(key=lambda it: support.channels_order.get(it.fulltitle, 999)) + support.thumb(itemlist, mode='live') + return itemlist + def search(item, text): - itemlist = [] - logger.debug(text) - item.search = text + item.args = {'uxReference':'main', 'params':'channel≈', 'query':text} try: - itemlist = peliculas(item) + return peliculas(item) + # Continua la ricerca in caso di errore except: import sys for line in sys.exc_info(): support.logger.error("%s" % line) - - return itemlist - - -def menu(item): - logger.debug() - itemlist = [] - if item.url: - json = get_from_id(item) - for it in json: - if 'uxReference' in it: itemlist.append( - item.clone(title=support.typo(it['title'], 'bullet bold'), url= it['landingUrl'], ref=it['uxReference'], args='', action='peliculas')) - return itemlist - - -def liveDict(): - livedict = OrderedDict({}) - json = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-stations?sort=ShortTitle').json()['entries'] - for it in json: - urls = [] - if it.get('tuningInstruction') and not it.get('mediasetstation$digitalOnly'): - guide=current_session.get('https://static3.mediasetplay.mediaset.it/apigw/nownext/' + it['callSign'] + '.json').json()['response'] - for key in it['tuningInstruction']['urn:theplatform:tv:location:any']: - urls += key['publicUrls'] - title = it['title'] - livedict[title] = {} - livedict[title]['urls'] = urls - livedict[title]['plot'] = support.typo(guide['currentListing']['mediasetlisting$epgTitle'],'bold') + '\n' + guide['currentListing']['mediasetlisting$shortDescription'] + '\n' + guide['currentListing']['description'] + '\n\n' + support.typo('A Seguire:' + guide['nextListing']['mediasetlisting$epgTitle'], 'bold') - return livedict - - -def live(item): - logger.debug() - itemlist = [] - for key, value in liveDict().items(): - itemlist.append(item.clone(title=support.typo(key, 'bold'), - fulltitle=key, - show=key, - contentTitle=key, - forcethumb=True, - urls=value['urls'], - plot=value['plot'], - action='play', - no_return=True)) - return support.thumb(itemlist, live=True) + return [] def peliculas(item): - logger.debug() itemlist = [] - titlelist = [] - contentType = '' - if item.text: - json = [] - itlist = [] - with futures.ThreadPoolExecutor() as executor: - for arg in ['searchMovie', 'searchStagioni', 'searchClip']: - item.args = ['', 'search', arg] - itlist += [executor.submit(get_programs, item)] - for res in futures.as_completed(itlist): - json += res.result() - else: - json = get_programs(item) - for it in json: - if item.search.lower() in it['title'].lower() and it['title'] not in titlelist: - titlelist.append(it['title']) - if 'media' in it: - action = 'findvideos' - contentType = 'movie' - urls = [] - for key in it['media']: - urls.append(key['publicUrl']) + res = get_programs(item) + video_id= '' + + for it in res['items']: + if not 'MediasetPlay_ANY' in it.get('mediasetprogram$channelsRights',['MediasetPlay_ANY']): continue + thumb = '' + fanart = '' + contentSerieName = '' + url = 'https:'+ it.get('mediasettvseason$pageUrl', it.get('mediasetprogram$videoPageUrl', it.get('mediasetprogram$pageUrl'))) + title = it.get('mediasetprogram$brandTitle', it.get('title')) + title2 = it['title'] + if title != title2: + title = '{} - {}'.format(title, title2) + plot = it.get('longDescription', it.get('description', it.get('mediasettvseason$brandDescription', ''))) + + if it.get('seriesTitle') or it.get('seriesTvSeasons'): + contentSerieName = it.get('seriesTitle', it.get('title')) + contentType = 'tvshow' + action = 'epmenu' + else: + contentType = 'movie' + video_id = it['guid'] + action = 'play' + for k, v in it['thumbnails'].items(): + if 'image_vertical' in k and not thumb: + thumb = v['url'].replace('.jpg', '@3.jpg') + if 'image_header_poster' in k and not fanart: + fanart = v['url'].replace('.jpg', '@3.jpg') + if thumb and fanart: + break + + itemlist.append(item.clone(title=support.typo(title, 'bold'), + fulltitle=title, + contentTitle=title, + contentSerieName=contentSerieName, + action=action, + contentType=contentType, + thumbnail=thumb, + fanart=fanart, + plot=plot, + url=url, + video_id=video_id, + seriesid = it.get('seriesTvSeasons', it.get('id','')), + disable_videolibrary = True, + forcethumb=True)) + if res['next']: + item.page = res['next'] + support.nextPage(itemlist, item) - else: - action = 'epmenu' - contentType = 'tvshow' - urls = it['mediasetprogram$brandId'] - if urls: - title = it['mediasetprogram$brandTitle'] + ' - ' if 'mediasetprogram$brandTitle' in it and it['mediasetprogram$brandTitle'] != it['title'] else '' - itemlist.append( - item.clone(channel=item.channel, - action=action, - title=support.typo(title + it['title'], 'bold'), - fulltitle=it['title'], - show=it['title'], - contentType=contentType if contentType else item.contentType, - contentTitle=it['title'] if 'movie' in [contentType, item.contentType] else '', - contentSerieName=it['title'] if 'tvshow' in [contentType, item.contentType] else '', - thumbnail=it['thumbnails']['image_vertical-264x396']['url'] if 'image_vertical-264x396' in it['thumbnails'] else '', - fanart=it['thumbnails']['image_keyframe_poster-1280x720']['url'] if 'image_keyframe_poster-1280x720' in it['thumbnails'] else '', - plot=it['longDescription'] if 'longDescription' in it else it['description'] if 'description' in it else '', - urls=urls, - seriesid = it.get('seriesId',''), - url=it['mediasetprogram$pageUrl'], - forcethumb=True, - no_return=True)) return itemlist - def epmenu(item): logger.debug() itemlist = [] + epUrl = 'https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-subbrands-v2?byTvSeasonId={}&sort=mediasetprogram$order' + if item.seriesid: - seasons = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-tv-seasons?bySeriesId=' + item.seriesid).json()['entries'] - for season in seasons: - if 'mediasettvseason$brandId' in season and 'mediasettvseason$displaySeason' in season: + if type(item.seriesid) == list: + res = [] + for s in item.seriesid: + itemlist.append( + item.clone(seriesid = s['id'], + title=support.typo(s['title'], 'bold'))) + if len(itemlist) == 1: return epmenu(itemlist[0]) + else: + res = requests.get(epUrl.format(item.seriesid)).json()['entries'] + for it in res: itemlist.append( item.clone(seriesid = '', - title=support.typo(season['mediasettvseason$displaySeason'], 'bold'), - urls=season['mediasettvseason$brandId'])) - itemlist = sorted(itemlist, key=lambda it: it.title, reverse=True) - if len(itemlist) == 1: return epmenu(itemlist[0]) - if not itemlist: - entries = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-brands?byCustomValue={brandId}{' + item.urls + '}').json()['entries'] - for entry in entries: - if 'mediasetprogram$subBrandId' in entry: - itemlist.append( - item.clone(action='episodios', - title=support.typo(entry['description'], 'bold'), - url=entry['mediasetprogram$subBrandId'], - order=entry.get('mediasetprogram$order',0))) - if len(itemlist) == 1: return episodios(itemlist[0]) - itemlist = sorted(itemlist, key=lambda it: it.order) - return itemlist + title=support.typo(it['description'], 'bold'), + subbrand=it['mediasetprogram$subBrandId'], + action='episodios')) + itemlist = sorted(itemlist, key=lambda it: it.title, reverse=True) + if len(itemlist) == 1: return episodios(itemlist[0]) + return itemlist def episodios(item): - logger.debug() + # create month list + months = [] + try: + for month in range(21, 33): months.append(xbmc.getLocalizedString(month)) + except: # per i test, xbmc.getLocalizedString non è supportato + for month in range(21, 33): months.append('dummy') + itemlist = [] - if not item.nextIndex: item.nextIndex = 1 + res = requests.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-programs-v2?byCustomValue={subBrandId}{' + item.subbrand +'}&sort=:publishInfo_lastPublished|asc,tvSeasonEpisodeNumber').json()['entries'] - url = 'https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-programs?byCustomValue={subBrandId}{'+ item.url + '}&range=' + str(item.nextIndex) + '-' + str(item.nextIndex + PAGINATION) - json = current_session.get(url).json()['entries'] + for it in res: + thumb = '' + titleDate = '' + if 'mediasetprogram$publishInfo_lastPublished' in it: + date = datetime.date.fromtimestamp(it['mediasetprogram$publishInfo_lastPublished'] / 1000) + titleDate =' [{} {}]'.format(date.day, months[date.month]) + title = '[B]{}[/B]{}'.format(it['title'], titleDate) + for k, v in it['thumbnails'].items(): + if 'image_keyframe' in k and not thumb: + thumb = v['url'].replace('.jpg', '@3.jpg') + break + if not thumb: thumb = item.thumbnail - for it in json: - urls = [] - if 'media' in it: - for key in it['media']: - urls.append(key['publicUrl']) - if urls: - title = it['title'] - itemlist.append( - item.clone(action='findvideos', - title=support.typo(title, 'bold'), - contentType='episode', - thumbnail=it['thumbnails']['image_vertical-264x396']['url'] if 'image_vertical-264x396' in it['thumbnails'] else '', - fanart=it['thumbnails']['image_keyframe_poster-1280x720']['url'] if 'image_keyframe_poster-1280x720' in it['thumbnails'] else '', - plot=it['longDescription'] if 'longDescription' in it else it['description'], - urls=urls, - url=it['mediasetprogram$pageUrl'], - year=it.get('year',''), - ep= it.get('tvSeasonEpisodeNumber', 0) if it.get('tvSeasonEpisodeNumber', 0) else 0, - forcethumb=True, - no_return=True)) - - if len(itemlist) == 1: return findvideos(itemlist[0]) - - if (len(json) >= PAGINATION): - item.nextIndex += PAGINATION + 1 - support.nextPage(itemlist, item) + itemlist.append(item.clone(title=title, + thumbnail=thumb, + forcethumb=True, + contentType='episode', + action='play', + video_id=it['guid'])) return itemlist -def findvideos(item): - logger.debug() - itemlist = [item.clone(server='directo', title='Mediaset Play', urls=item.urls, action='play')] - return support.server(item, itemlist=itemlist, Download=False) - - def play(item): logger.debug() - for url in item.urls: - sec_data = support.match(url + post_url).data + item.no_return=True + mpd = config.get_setting('mpd', item.channel) + + + lic_url = 'https://widevine.entitlement.theplatform.eu/wv/web/ModularDrm/getRawWidevineLicense?releasePid={pid}&account=http://access.auth.theplatform.com/data/Account/2702976343&schema=1.0&token={token}|Accept=*/*&Content-Type=&User-Agent={ua}|R{{SSM}}|' + url = '' + + if item.urls: + url = '' + pid = '' + Format = 'dash+xml' if mpd else 'x-mpegURL' + for it in item.urls: + if Format in it['format']: + item.url = requests.head(it['publicUrls'][0]).headers['Location'] + pid = it['releasePids'][0] + + if mpd: + item.manifest = 'mpd' + item.drm = 'com.widevine.alpha' + item.license = lic_url.format(pid=pid, token=Token, ua=support.httptools.get_user_agent()) + + else: + item.manifest = 'hls' + return[item] + + elif item.video_id: + payload = '{"contentId":"' + item.video_id + ' ","streamType":"VOD","delivery":"Streaming","createDevice":true}' + res = session.post('https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0?sid=' + sid, data=payload).json()['response']['mediaSelector'] + + else: + payload = '{"channelCode":"' + item.callSign + '","streamType":"LIVE","delivery":"Streaming","createDevice":true}' + res = session.post('https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0?sid=' + sid, data=payload).json()['response']['mediaSelector'] + + url = res['url'] + mpd = True if 'dash' in res['formats'].lower() else False + + if url: + + sec_data = support.match(url + '?' + urlencode(res)).data item.url = support.match(sec_data, patron=r'<video src="([^"]+)').match pid = support.match(sec_data, patron=r'pid=([^|]+)').match - item.manifest = 'mpd' - if pid: + if mpd and pid: + item.manifest = 'mpd' item.drm = 'com.widevine.alpha' - item.license = lic_url % pid - break + item.license = lic_url.format(pid=pid, token=Token, ua=support.httptools.get_user_agent()) + else: + item.manifest = 'hls' - return [item] - - -def subBrand(json): - logger.debug() - subBrandId = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-brands?byCustomValue={brandId}{' + json + '}').json()['entries'][-1]['mediasetprogram$subBrandId'] - json = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-programs?byCustomValue={subBrandId}{' + subBrandId + '}').json()['entries'] - return json + return [item] def get_from_id(item): logger.debug() - json = current_session.get(entry.format(id=item.url)).json() - if 'components' in json: - id = quote(",".join(json["components"])) - json = current_session.get(entries.format(id=id)).json() - if 'entries' in json: - return json['entries'] + sessionKey = session.get(sessionUrl.format(uuid=str(uuid.uuid4())), verify=False).json()['sessionKey'] + session.headers.update({'x-session': sessionKey}) + res = session.get(entry.format(id=item.args)).json() + if 'components' in res: + id = quote(",".join(res["components"])) + res = session.get(entries.format(id=id)).json() + if 'entries' in res: + return res['entries'] return {} - -def get_programs(item, ret=[], args={}): - hasMore = False +def get_programs(item): url = '' + pag = item.page if item.page else 1 + ret = {} - if 'search' in item.args: - args['uxReference'] = item.args[2] - args["query"] = item.text - args['traceCid'] = tracecid - args['cwId'] = cwid - args['page'] = 1 - args['platform'] = 'pc' - args['hitsPerPage'] = 500 - url = 'https://api-ott-prod-fe.mediaset.net/PROD/play/rec2/search/v1.0?' + urlencode(args) - elif not args: - if item.ref in cdict: - args['uxReference'] = cdict[item.ref] - args['platform'] = 'pc' - else: - args = {"query": "*:*"} - if item.args[2]: - args['categories'] = item.args[2] + if item.args.get('feed'): + pag = item.page if item.page else 1 + url='{}&range={}-{}'.format(item.args.get('feed'), pag, pag + pagination - 1) + ret['next'] = pag + pagination + res = requests.get(url).json() - args['cwId'] = cwid - args['traceCid'] = tracecid - args['hitsPerPage'] = 500 - args['page'] = '0' - args['deviceId'] = deviceid - url="https://api-ott-prod-fe.mediaset.net/PROD/play/rec2/cataloguelisting/v1.0?" + urlencode(args) - - # if 'all' in item.args: url = 'https://api-ott-prod-fe.mediaset.net/PROD/play/rec/azlisting/v1.0?' + urlencode(args) - if url: - json = current_session.get(url).json() - if 'response' in json: - json = json['response'] - if 'hasMore' in json: - hasMore = json['hasMore'] - if 'components' in json: - id = quote(",".join(json["components"])) - json = current_session.get(entries.format(id=id)).json() - if 'entries' in json: - ret += json['entries'] - if hasMore: - args['page'] = str(int(args['page']) + 1) - return get_programs(item, ret, args) - else: - return ret else: - return ret + args = {key:value for key, value in item.args.items()} + args['context'] = 'platform≈web' + args['sid'] = sid + args['sessionId'] = sid + args['hitsPerPage'] = pagination + args['property'] = 'search' if args.get('query') else 'play' + args['tenant'] = 'play-prod-v2' + args['page'] = pag + args['deviceId'] = '017ac511182d008322c989f3aac803083002507b00bd0' + url="https://api-ott-prod-fe.mediaset.net/PROD/play/reco/anonymous/v2.0?" + urlencode(args) + + res = session.get(url).json() + + if res: + res = res.get('response', res) + if 'entries' in res: + ret['items'] = res['entries'] + elif 'blocks' in res: + items = [] + for block in res['blocks']: + items += block['items'] + ret['items'] = items + if not 'next' in ret: + next = res.get('pagination',{}).get('hasNextPage', False) + ret['next'] = pag + 1 if next else 0 + return ret + + + + + + diff --git a/channels/mediasetplay.py.old b/channels/mediasetplay.py.old index dd41d490..d52a75e2 100644 --- a/channels/mediasetplay.py.old +++ b/channels/mediasetplay.py.old @@ -150,7 +150,7 @@ def live(item): plot=value['plot'], action='play', no_return=True)) - return support.thumb(itemlist, live=True) + return support.thumb(itemlist, mode='live') def peliculas(item): diff --git a/channels/paramount.py b/channels/paramount.py index 2c22cbd7..56b89165 100644 --- a/channels/paramount.py +++ b/channels/paramount.py @@ -65,7 +65,7 @@ def live(item): itemlist=[] for key, value in liveDict().items(): itemlist.append(item.clone(title=support.typo(key,'bold'), contentTitle=key, fulltitle=key, show=key, url=value['url'], plot=value['plot'], action='play', forcethumb=True, no_return=True)) - return support.thumb(itemlist, live=True) + return support.thumb(itemlist, mode='live') def peliculas(item): @@ -174,5 +174,5 @@ def play(item): if item.livefilter: d = liveDict()[item.livefilter] item = item.clone(title=support.typo(item.livefilter, 'bold'), fulltitle=item.livefilter, url=d['url'], plot=d['plot'], action='play', forcethumb=True, no_return=True) - support.thumb(item, live=True) + support.thumb(item, mode='live') return [item] \ No newline at end of file diff --git a/channels/raiplay.py b/channels/raiplay.py index e394be75..e969da05 100644 --- a/channels/raiplay.py +++ b/channels/raiplay.py @@ -3,35 +3,35 @@ # Canale per Rai Play # ------------------------------------------------------------ -import requests, sys, inspect -from core import support, channeltools -from platformcode import autorenumber, logger, platformtools -from collections import OrderedDict +from core.item import Item +import datetime, xbmc +import requests, sys + +from core import jsontools, support +from platformcode import logger + if sys.version_info[0] >= 3: from concurrent import futures else: from concurrent_py2 import futures -current_session = requests.Session() host = support.config.get_channel_url() -onair = host + '/palinsesto/onAir.json' - @support.menu def mainlist(item): - top = [('Dirette {bold}', ['', 'live']), - ('Replay {bold}', ['/dl/RaiPlay/2016/PublishingBlock-9a2ff311-fcf0-4539-8f8f-c4fee2a71d58.html?json', 'replay_menu'])] + top = [('Dirette {bold}', ['/dirette', 'live', '/palinsesto/onAir.json']), + ('Replay {bold}', ['/guidatv', 'replayMenu', '/guidatv.json'])] - menu = [('Film {bullet bold}', ['/tipologia/film/index.json', 'menu']), - ('Serie TV {bullet bold}', ['/tipologia/serietv/index.json', 'menu']), - ('Fiction {bullet bold}', ['/tipologia/fiction/index.json', 'menu']), - ('Documentari {bullet bold}', ['/tipologia/documentari/index.json', 'menu']), - ('Programmi TV{bullet bold}', ['/tipologia/programmi/index.json', 'menu']), - ('Programmi per Bambini {bullet bold}', ['/tipologia/bambini/index.json', 'menu']), - ('Teen {bullet bold}', ['/tipologia/teen/index.json', 'learning']), - ('Learning {bullet bold}', ['/tipologia/learning/index.json', 'learning']), - ('Teche Rai {bullet bold storia}', ['/tipologia/techerai/index.json', 'menu']), - ('Musica e Teatro {bullet bold}', ['/tipologia/musica-e-teatro/index.json', 'menu']) + menu = [('Film {bullet bold}', ['/film', 'menu', '/tipologia/film/index.json']), + ('Serie TV {bullet bold}', ['/serietv', 'menu', '/tipologia/serietv/index.json']), + ('Fiction {bullet bold}', ['/fiction', 'menu', '/tipologia/fiction/index.json']), + ('Documentari {bullet bold}', ['/documentari', 'menu', '/tipologia/documentari/index.json']), + ('Programmi TV{bullet bold}', ['/programmi', 'menu', '/tipologia/programmi/index.json']), + ('Programmi per Bambini {bullet bold}', ['/bambini', 'menu', '/tipologia/bambini/index.json']), + ('Teen {bullet bold}', ['/teen', 'menu', '/tipologia/teen/index.json']), + ('Learning {bullet bold}', ['/learning', 'menu', '/tipologia/learning/index.json']), + ('Teche Rai {bullet bold storia}', ['/techerai', 'menu', '/tipologia/techerai/index.json']), + ('Musica e Teatro {bullet bold}', ['/musica-e-teatro', 'menu', '/tipologia/musica-e-teatro/index.json']) ] search = '' @@ -40,46 +40,115 @@ def mainlist(item): def menu(item): - support.info() - itemlist = [item.clone(title = support.typo('Tutti','bullet bold'), action = 'peliculas'), - item.clone(title = support.typo('Generi','submenu'), args = 'genre', action = 'submenu'), - item.clone(title = support.typo('A-Z','submenu'), args = 'az', action = 'submenu'), - item.clone(title = support.typo('Cerca','submenu'), action = 'search')] + logger.debug() + itemlist = [] + item.disable_videolibrary = True + action = 'peliculas' - return support.thumb(itemlist) + if item.data: + for it in item.data: + url = getUrl(it['path_id']) + action = 'genres' + itemlist.append(item.clone(title=support.typo(it['name'], 'bold'), url=url.replace('.json','.html'), genre_url=url, data='', action=action)) + support.thumb(itemlist, mode='genre') + else: + items = item.data if item.data else requests.get(host + item.args).json()['contents'] + for it in items: + if 'RaiPlay Slider Block' in it['type'] or 'RaiPlay Slider Generi Block' in it['type']: + thumb = item.thumbnail + if 'RaiPlay Slider Generi Block' in it['type']: + action = 'menu' + thumb = support.thumb('genres') + itemlist.append(item.clone(title=support.typo(it['name'], 'bold'), data=it.get('contents', item.data), thumbnail=thumb, action=action)) - -def learning(item): - support.info() - itemlist =[] - json = current_session.get(item.url).json()['contents'] - for key in json: - itemlist.append(item.clone(title = support.typo(key['name'],'bold'), fulltitle = key['name'], - show = key['name'], data = key['contents'], action = 'peliculas')) return itemlist -def submenu(item): - support.info() +def genres(item): itemlist = [] - json = current_session.get(item.url).json()['contents'][-1]['contents'] - if item.args == 'az': - json_url = getUrl(json[-1]['path_id']) - json = current_session.get(json_url).json()['contents'] - for key in json: - itemlist.append(item.clone(title = support.typo(key,'bold'), fulltitle = key, - show = key, data = json[key], action = 'peliculas')) - else: - for key in json: - itemlist.append(item.clone(title = support.typo(key['name'],'bold'), fulltitle = key['name'], show = key['name'], - thumbnail = getUrl(key['image']), url = getUrl(key['path_id']), action = 'peliculas')) - itemlist.pop(-1) - return support.thumb(itemlist) + items = requests.get(getUrl(item.genre_url)).json()['contents'] + for title, it in items.items(): + if it: itemlist.append(item.clone(title=support.typo(title, 'bold'), data=it, action='peliculas', thumbnail=support.thumb('az'))) + return itemlist -def replay_menu(item): - support.info() - import datetime, xbmc +def search(item, text): + logger.debug(text) + post = {'page':0, 'pagesize': 1000, 'param':text} + + try: + item.data = requests.post(host + '/atomatic/raiplay-search-service/api/v3/search', json=post).json()['agg']['titoli']['cards'] + return peliculas(item) + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.logger.error("%s" % line) + return [] + + +def peliculas(item): + logger.debug() + return addinfo(item.data, item) + + +def episodios(item): + logger.debug() + itemlist = [] + + if item.data: + items = item.data + elif item.season_url: + items = requests.get(item.season_url).json()['items'] + elif item.video_url: + items = requests.get(item.video_url).json()['blocks'] + + if 'sets' in items[0]: + if len(items) > 1: + itemlist = epMenu(item.clone(data=items)) + else: + if len(items[0]['sets']) > 1: + itemlist = epMenu(item.clone(data=items[0]['sets'])) + else: + items = requests.get(getUrl(items[0]['sets'][0]['path_id'])).json()['items'] + + if not itemlist: + itemlist = addinfo(items, item) + + return itemlist + + +def epMenu(item): + video_url = '' + itemlist = [] + for it in item.data: + if 'sets' in it: + itemlist.append(item.clone(title=support.typo(it['name'], 'bold'), data=[it])) + else: + itemlist.append(item.clone(title=support.typo(it['name'], 'bold'), season_url=getUrl(it['path_id']), data='')) + return itemlist + + +def live(item): + logger.debug() + itemlist = [] + item.forcethumb = True + items = requests.get(getUrl(item.args)).json()['on_air'] + for it in items: + title = it['channel'] + url = '{}/dirette/{}'.format(host, title.lower().replace(' ','')) + fanart = getUrl(it['currentItem']['image']) + current = it['currentItem'] + next = it['nextItem'] + plot = '[B]{}[/B]\n{}\n\nA Seguire: [B]{}[/B]\n{}'.format(current['name'], current['description'], next['name'], next['description']) + itemlist.append(item.clone(title=title, fulltitle=title, fanart=fanart, plot=plot, url=url, video_url=url + '.json', action='play')) + itemlist.sort(key=lambda it: support.channels_order.get(it.fulltitle, 999)) + support.thumb(itemlist, mode='live') + return itemlist + + +def replayMenu(item): + logger.debug() # create day and month list days = [] @@ -98,336 +167,133 @@ def replay_menu(item): today = datetime.date.today() for d in range(7): day = today - datetime.timedelta(days=d) - support.info(day) - itemlist.append(item.clone(action = 'replay_channels', date = day.strftime("%d-%m-%Y"), - title = support.typo(days[int(day.strftime("%w"))] + " " + day.strftime("%d") + " " + months[int(day.strftime("%m"))-1], 'bold'))) + dayName = days[int(day.strftime("%w"))] + dayNumber = day.strftime("%d") + monthName = months[int(day.strftime("%m"))-1] + title = '{} {} {}'.format(dayName, dayNumber, monthName) + itemlist.append(item.clone(title = support.typo(title, 'bold'), + action='replayChannels', + date=day.strftime("%d-%m-%Y"))) return itemlist -def replay_channels(item): - support.info() +def replayChannels(item): + logger.debug() itemlist = [] - json = current_session.get(item.url).json()['dirette'] - for key in json: - itemlist.append(item.clone(title = support.typo(key['channel'], 'bold'), fulltitle = key['channel'], show = key['channel'], plot = item.title, action = 'replay', - thumbnail = key['transparent-icon'].replace("[RESOLUTION]", "256x-"), url = '%s/palinsesto/app/old/%s/%s.json' % (host, key['channel'].lower().replace(' ','-'), item.date))) - return itemlist + items = requests.get(getUrl(item.args)).json()['channels'] + for it in items: + if 'RaiPlay' in it['name']: continue + url = '{}?channel={}&date={}'.format(item.url, it['absolute_path'], item.date) + channel_url = '{}/palinsesto/app/{}/{}.json'.format(host, it['absolute_path'], item.date) + itemlist.append(item.clone(title=support.typo(it['label'], 'bold'), + fulltitle=it['label'], + url=url, + channel_url=channel_url, + action='replay')) + itemlist.sort(key=lambda it: support.channels_order.get(it.fulltitle, 999)) + support.thumb(itemlist, mode='live') + return itemlist def replay(item): - support.info() + logger.debug() + + def itInfo(it): + info = requests.get(getUrl(it['program']['info_url'])).json() + image = getUrl(info['images']['landscape']) + return item.clone(title = '{} - {}'.format(it['hour'], it['name']), + thumbnail = image, + fanart = image, + plot = info['description'], + url = getUrl(it['weblink']), + video_url = getUrl(it['path_id']), + action = 'play', + forcethumb = True) + + itemlist = [] - json = current_session.get(item.url).json()[item.fulltitle][0]['palinsesto'][0]['programmi'] - for key in json: - support.info('KEY=',key) - if key and key['pathID']: itemlist.append(item.clone(thumbnail = getUrl(key['images']['landscape']), fanart = getUrl(key['images']['landscape']), url = getUrl(key['pathID']), fulltitle = key['name'], show = key['name'], - title = support.typo(key['timePublished'], 'color kod bold') + support.typo(' | ' + key['name'], ' bold'), plot = key['testoBreve'], action = 'findvideos')) - return itemlist - -def search(item, text): - support.info() - itemlist =[] - try: - if item.url != host: - item.search = text - itemlist = peliculas(item) - else: - json = current_session.get(host + '/dl/RaiTV/RaiPlayMobile/Prod/Config/programmiAZ-elenco.json').json() - for key in json: - for key in json[key]: - if 'PathID' in key and (text.lower() in key['name'].lower()): - itemlist.append(item.clone(title = support.typo(key['name'],'bold'), fulltitle = key['name'], show = key['name'], url = key['PathID'].replace('/?json', '.json'), action = 'Type', - thumbnail = getUrl(key['images']['portrait'] if 'portrait' in key['images'] else key['images']['portrait43'] if 'portrait43' in key['images'] else key['images']['landscape']), - fanart = getUrl(key['images']['landscape'] if 'landscape' in key['images'] else key['images']['landscape43']))) - except: - import sys - for line in sys.exc_info(): - support.logger.error("%s" % line) - return [] - return itemlist - - -def Type(item): - logger.debug(item.url) - json = current_session.get(item.url).json() - if json['program_info']['layout'] == 'single': - item.contentTitle = item.fulltitle - item.contentType = 'movie' - return findvideos(item) - else: - item.contentType = 'tvshow' - return select(item) - - -def liveDict(): - livedict = OrderedDict({}) - info = {} - url = host + '/dirette.json' - json = current_session.get(url).json()['contents'] - onAir = current_session.get(onair).json()['on_air'] - for key in onAir: - channel = key['channel'] - info[channel] = {} - info[channel]['fanart'] = getUrl(key['currentItem']['image']) - info[channel]['plot'] = support.typo(key['currentItem']['name'],'bold')+ '\n\n' + key['currentItem']['description'] - for key in json: - channel = key['channel'] - livedict[channel] = {} - livedict[channel]['url'] = key['video']['content_url'] - livedict[channel]['plot'] = info[channel]['plot'] - livedict[channel]['fanart'] = info[channel]['fanart'] - - return livedict - - -def live(item): - support.info() - itemlist =[] - for channel, value in liveDict().items(): - itemlist.append(item.clone(title = support.typo(channel, 'bold'), fulltitle = channel, show = channel, url = value['url'], - plot = value['plot'], action = 'play', fanart = value['fanart'], manifest='hls', no_return=True)) - return support.thumb(itemlist, live=True) - - -def peliculas(item): - support.info() - itemlist = [] - keys = [] - key_list = [] - - # pagination options - pag = item.page if item.page else 1 - pagination = 40 if not item.search else '' - - # load json - if item.data: - json = item.data - for key in json: - if item.search.lower() in key['name'].lower(): - keys.append(key) - else: - json = current_session.get(item.url).json() - - # load json for main menu item - if not item.args: - json_url = getUrl(json['contents'][-1]['contents'][-1]['path_id']) - json = current_session.get(json_url).json()['contents'] - else: - json = json['contents'] - for key in json: - if len(json[key]) > 0: - for key in json[key]: - if item.search.lower() in key['name'].lower(): - keys.append(key) - - # load titles - for i, key in enumerate(keys): - if pagination and (pag - 1) * pagination > i: continue # pagination - if pagination and i >= pag * pagination: break - key_list.append(key) + items = requests.get(item.channel_url).json().get('events', {}) + now = datetime.datetime.now() + h = int('{}{:02d}'.format(now.hour, now.minute)) with futures.ThreadPoolExecutor() as executor: - itlist = [executor.submit(addinfo, key, item) for key in key_list] + itlist = [executor.submit(itInfo, it) for it in items if it['has_video'] and int(it['hour'].replace(':','')) <= h] for res in futures.as_completed(itlist): if res.result(): itemlist.append(res.result()) - itemlist = sorted(itemlist, key=lambda it: it.title) - - if not item.search and len(keys) > pag * pagination: - itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'), page=pag + 1, thumbnail=support.thumb())) + if not itemlist: + return [Item(title='Non ci sono Replay per questo Canale')] return itemlist +def play(item): + logger.debug() -def select(item): - support.info() - itemlist = [] - if type(item.data) in [list, dict]: - json = item.data - else: - json = current_session.get(item.url).json() - if 'blocks' in json: - json = json['blocks'] - season = '' - for key in json: - if item.fulltitle in key['name']: season = key['name'].replace(item.fulltitle, '').strip() - if not season.isdigit(): season = '' - itemlist.append(item.clone(title = support.typo(key['name'],'bold'), season = season, data = key['sets'], action = 'select')) - if len(itemlist) == 1: - return select(itemlist[0]) - else: - if item.data: - for key in item.data: - itemlist.append(item.clone(title = support.typo(key['name'], 'bold'), data = getUrl(key['path_id']), url = getUrl(key['path_id']), contentType = 'tvshow', action = 'episodios')) - if len(itemlist) == 1: - return episodios(itemlist[0]) - elif 'contents' in json: - for letter in json['contents'].keys(): - if json['contents'][letter]: - itemlist.extend(peliculas(item.clone(data=json['contents'][letter]))) - return itemlist + res = requests.get(item.video_url).json() + + if 'first_item_path' in res: + res = requests.get(getUrl(res['first_item_path'])).json() + + url, lic = support.match(res['video']['content_url'] + '&output=56', patron=r'content"><!\[CDATA\[([^\]]+)(?:.*?"WIDEVINE","licenceUrl":"([^"]+))?').match + + if lic: + item.drm = 'com.widevine.alpha' + item.license = lic + '|' + host + '|R{SSM}|' + + item = item.clone(server='directo', url=url, no_return=True, manifest='hls') + + return [item] -def episodios(item): - support.info() - itemlist = [] - if type(item.data) in [list, dict] and len(item.data) > 1 and ('name' in item.data[0] and 'stagione' not in item.data[0]['name'].lower()): - for key in item.data: - itemlist.append(item.clone(title = support.typo(key['name'], 'bold'), url = getUrl(key['path_id']), contentType = 'tvshow', action = 'episodios')) +def getUrl(url): + logger.debug() - elif type(item.data) in [list, dict]: - for key in item.data: - load_episodes(key, item) - with futures.ThreadPoolExecutor() as executor: - itlist = [executor.submit(load_episodes, key, item) for key in item.data] - for res in futures.as_completed(itlist): - if res.result(): - itemlist += res.result() - if itemlist and itemlist[0].VL: - # itemlist.reverse() - itemlist = sorted(itemlist, key=lambda it: it.order) - item.action = 'episodios' - support.videolibrary(itemlist, item) - else: - itemlist = sorted(itemlist, key=lambda it: it.title) + if url.startswith("/raiplay/"): url = url.replace("/raiplay/", host +'/') + elif url.startswith("//"): url = "https:" + url + elif url.startswith("/"): url = host + url - else: - date = '' - if type(item.data) in [list, dict]: item.data = getUrl(item.url[0]['path_id']) - json = current_session.get(item.url).json()['items'] - for key in json: - ep = support.match(key['subtitle'], patron=r'(?:St\s*(\d+))?\s*Ep\s*(\d+)').match - if ep: - season = '1' if not ep[0] else ep[0] - episode = ep[1].zfill(2) - title = support.re.sub(r'(?:St\s*\d+)?\s*Ep\s*\d+','',key['subtitle']) - title = season + 'x' + episode + (' - ' + title if not title.startswith(' ') else title if title else '') - elif item.season and support.match(item.title.lower(), patron =r'(puntate)').match: - title = key['subtitle'].strip() - if not title: title = key['name'] - date = support.match(title, patron=r'(\d+/\d+/\d+)').match - if date: - date = title.split('/') - date = date[2][-2] + '/' + date[1] + '/' + date[0] - - else: - title = key['subtitle'].strip() - if not title: - title = key['name'] - itemlist.append(item.clone(title = support.typo(title, 'bold'), action = 'findvideos', VL=True if ep else False, plot = key['description'], - fanart = getUrl(key['images']['landscape']), url = key['video_url'], contentType = 'episode', date=date)) - - if item.season and support.match(item.title.lower(), patron =r'(puntate)').match: - itemlist = sorted(itemlist, key=lambda it: it.date) - for i, it in enumerate(itemlist): - episode = str(i + 1) - it.title = support.typo(item.season + 'x' + episode, 'bold') + (' - ' + it.title) - - if itemlist and itemlist[0].VL: support.videolibrary(itemlist, item) - - if itemlist and not support.match(itemlist[0].title, patron=r'[Ss]?(\d+)(?:x|_|\.|\s+)[Ee]?[Pp]?(\d+)').match and inspect.stack()[1][3] not in ['find_episodes']: - autorenumber.start(itemlist, item) - return itemlist - - -def findvideos(item): - support.info() - itemlist = [] - if item.url.endswith('json'): - json = current_session.get(item.url).json() - - if 'first_item_path' in json: - url = current_session.get(getUrl(json['first_item_path'])).json()['video']['content_url'] - else: - url = json['video']['content_url'] - else: - url = item.url - - itemlist.append(item.clone(server = 'directo', title = 'Rai Play', url = getUrl(url) + '&output=56', action = 'play')) - return support.server(item, itemlist=itemlist, Download=False) - - -def getUrl(pathId): - support.info() - url = pathId.replace(" ", "%20") - if url.startswith("/raiplay/"): - url = url.replace("/raiplay/",host +'/') - - if url.startswith("//"): - url = "https:" + url - elif url.startswith("/"): - url = host + url - - # fix format of url for json - if url.endswith(".html?json"): - url = url.replace(".html?json", ".json") - elif url.endswith("/?json"): - url = url.replace("/?json",".json") - elif url.endswith("?json"): - url = url.replace("?json",".json") + url = url.replace(".html?json", ".json").replace("/?json",".json").replace("?json",".json").replace(" ", "%20") return url -def addinfo(key, item): - support.info() - info = current_session.get(getUrl(key['info_url'])).json() if 'info_url' in key else {} - if 'images' in key: - fanart = key['images']['landscape'] - if key['images']['portrait_logo']: - thumb = key['images']['portrait_logo'] +def addinfo(items, item): + def itInfo(key, item): + logger.debug(jsontools.dump(key)) + item.forcethumb = True + if key.get('titolo', ''): + key = requests.get(getUrl(key['path_id'])).json()['program_info'] + + + info = requests.get(getUrl(key['info_url'])).json() if 'info_url' in key else {} + + images = info.get('images', {}) + fanart = images.get('landscape', '') + thumb = images.get('portrait_logo', '') + if not thumb: thumb = fanart + title = key.get('name', '') + + it = item.clone(title=support.typo(title, 'bold'), + data='', + fulltitle=title, + show=title, + thumbnail= getUrl(thumb), + fanart=getUrl(fanart), + url=getUrl(key.get('weblink', '')), + video_url=getUrl(key['path_id']), + plot=info.get('description', '')) + + if 'Genere' not in key.get('sub_type', '') and ('layout' not in key or key['layout'] == 'single'): + it.action = 'play' + it.contentTitle = it.fulltitle else: - thumb = key['images']['landscape'] - else: - thumb = '' - fanart = '' - it = item.clone(title=support.typo(key.get('name', ''), 'bold'), fulltitle=key.get('name', ''), - show=key.get('name', ''), data='', thumbnail=getUrl(thumb), - fanart=getUrl(fanart), url=getUrl(key['path_id']), plot=info.get('description', '')) + it.action = 'episodios' + it.contentSerieName = it.fulltitle + return it - if 'Genere' not in key.get('sub_type', '') and ('layout' not in key or key['layout'] == 'single'): - it.action = 'findvideos' - it.contentType = 'movie' - it.contentTitle = it.fulltitle - else: - it.action = 'select' - it.contentType = 'tvshow' - it.contentSerieName = it.fulltitle - return it - - -def load_episodes(key, item): - support.info() itemlist = [] - json = current_session.get(getUrl(key['path_id'])).json()['items'] - order = 0 - for key in json: - ep = support.match(key['subtitle'], patron=r'(?:St\s*(\d+))?\s*Ep\s*(\d+)').match - if ep: - season = '1' if not ep[0] else ep[0] - episode = ep[1].zfill(2) - title = season + 'x' + episode + support.re.sub(r'(?:St\s*\d+)?\s*Ep\s*\d+','',key['subtitle']) - order = int(season + episode) - else: - title = key['subtitle'].strip() - if not title: - title = key['name'] - - itemlist.append(item.clone(title = support.typo(title, 'bold'), url = key['video_url'], contentType = 'episode', - fanart = getUrl(key['images']['landscape']), plot = key['description'], - action = 'findvideos', VL=True if ep else False, order=order)) - return itemlist - - -def play(item): - if item.livefilter: - d = liveDict() - item = item.clone(server='directo', fulltitle=item.livefilter, url=d[item.livefilter]['url'], plot=d[item.livefilter]['plot'], forcethumb=True, no_return=True) - support.thumb(item, live=True) - if '&output=56' in item.url: - match = support.match(item, patron=r'content"><!\[CDATA\[([^\]]+)(?:.*?"WIDEVINE","licenceUrl":"([^"]+))?').match - item.url = match[0] - if len(match) == 2: - item.drm = 'com.widevine.alpha' - item.license = match[1] + '|' + host + '|R{SSM}|' - logger.debug('PLAY URL', item.url) - return [item] \ No newline at end of file + with futures.ThreadPoolExecutor() as executor: + itlist = [executor.submit(itInfo, it, item) for it in items] + for res in futures.as_completed(itlist): + if res.result(): + itemlist.append(res.result()) + return itemlist \ No newline at end of file diff --git a/channels/seriehd.json b/channels/seriehd.json index eda29eb2..9c7ade33 100644 --- a/channels/seriehd.json +++ b/channels/seriehd.json @@ -1,7 +1,7 @@ { "id": "seriehd", "name": "SerieHD", - "active": true, + "active": false, "language": ["ita"], "thumbnail": "seriehd.png", "banner": "seriehd.png", diff --git a/channels/seriehd.py b/channels/seriehd.py index 29d47500..ce8c4954 100644 --- a/channels/seriehd.py +++ b/channels/seriehd.py @@ -17,10 +17,10 @@ def mainlist(item): tvshow = [('Genere', ['', 'menu', 'genre']), ('A-Z', ['', 'menu', 'a-z']), - ('In Corso', ['category/serie-tv-streaming/serie-in-corso', 'peliculas']), - ('Complete', ['category/serie-tv-streaming/serie-complete', 'peliculas']), - ('Americane', ['category/serie-tv-streaming/serie-tv-americane', 'peliculas']), - ('Italiane', ['category/serie-tv-streaming/serie-tv-italiane', 'peliculas']), + ('In Corso', ['/category/serie-tv-streaming/serie-in-corso', 'peliculas']), + ('Complete', ['/category/serie-tv-streaming/serie-complete', 'peliculas']), + ('Americane', ['/category/serie-tv-streaming/serie-tv-americane', 'peliculas']), + ('Italiane', ['/category/serie-tv-streaming/serie-tv-italiane', 'peliculas']), ('Ultimi Episodi', ['/aggiornamenti', 'peliculas', 'last']), ('Evidenza', ['', 'peliculas', 'best'])] return locals() diff --git a/channels/streamingcommunity.py b/channels/streamingcommunity.py index 0ff58114..cb3e3fbc 100644 --- a/channels/streamingcommunity.py +++ b/channels/streamingcommunity.py @@ -52,7 +52,7 @@ def genres(item): args = support.match(data, patronBlock=r'genre-options-json="([^\]]+)\]', patron=r'name"\s*:\s*"([^"]+)').matches for arg in args: itemlist.append(item.clone(title=support.typo(arg, 'bold'), args=arg, action='peliculas')) - support.thumb(itemlist, genre=True) + support.thumb(itemlist, mode='genre') return itemlist diff --git a/channels/tantifilm.py b/channels/tantifilm.py index f255d411..116a5ab8 100644 --- a/channels/tantifilm.py +++ b/channels/tantifilm.py @@ -133,7 +133,7 @@ def search(item, texto): @support.scrape def newest(categoria): if categoria == 'series': - item = Item(url=host + '/aggiornamenti-giornalieri-serie-tv') + item = Item(url=host + '/aggiornamenti-serie-tv') data = support.match(item).data.replace('<u>','').replace('</u>','') item.contentType = 'episode' patronBlock = r'Aggiornamenti Giornalieri Serie TV.*?<div class="sp-body folded">(?P<block>.*?)</div>' diff --git a/channels/tapmovie.py b/channels/tapmovie.py index 76459651..e9d2637f 100644 --- a/channels/tapmovie.py +++ b/channels/tapmovie.py @@ -49,7 +49,7 @@ def genres(item): itemlist = [] for n, genre in enumerate(httptools.downloadpage(host + api_url + 'categories', post={}).json.get('categories', [])): itemlist.append(item.clone(action="peliculas", genre=genre.get('name'), title=genre.get('value'), n=n)) - return support.thumb(itemlist, genre=True) + return support.thumb(itemlist, mode='genre') def peliculas(item, text=''): diff --git a/channels/toonitalia.py b/channels/toonitalia.py index f3958941..2a16dae9 100644 --- a/channels/toonitalia.py +++ b/channels/toonitalia.py @@ -71,7 +71,7 @@ def peliculas(item): #patron = r'href="(?P<url>[^"]+)" title="(?P<title>[^"]+)"' patron = r'<a href="(?P<url>[^"]+)"[^>]*>(?P<title>[^<]+)<[^>]+>[^>]+>\s*<div' elif item.args == 'last': - patronBlock = 'Aggiornamenti</h2>(?P<block>.*)</ul>' + patronBlock = '(?:Aggiornamenti|Update)</h2>(?P<block>.*?)</ul>' patron = r'<a href="(?P<url>[^"]+)">\s*<img[^>]+src[set]{0,3}="(?P<thumbnail>[^ ]+)[^>]+>\s*<span[^>]+>(?P<title>[^<]+)' else: patronBlock = '<main[^>]+>(?P<block>.*)</main>' @@ -93,17 +93,15 @@ def peliculas(item): @support.scrape def episodios(item): anime = True - def get_ep(item): - find = '' - data = support.match(item, headers=headers).data - match = support.match(data, patron=r'(?: /> |<p>)(?:(?P<season>\d+)×)?(?P<episode>\d+)(?:\s+–\s+)?(?P<title>[^<]+)<a (?P<data>.*?)(?:<br|</p)').matches - if match: - for m in match: - find += '{}{:02d}|{}|{}|'.format(m[0]+'x' if m[0] else '', int(m[1]), clean_title(m[2]), m[3]) - return find - - data = get_ep(item) - patron = r'(?P<episode>[^|]+)\|(?P<title>[^|]+)\|(?P<data>[^|]+)\|' + # debug = True + patron = r'>\s*(?:(?P<season>\d+)(?:×|x|×))?(?P<episode>\d+)(?:\s+–\s+)?[ –]+(?P<title2>[^<]+)[ –]+<a (?P<data>.*?)(?:<br|</p)' + # data = '' + # match = support.match(item, headers=headers, patron=r'(?: /> |<p>)(?:(?P<season>\d+)×)?(?P<episode>\d+)(?:\s+–\s+)?(?P<title>[^<]+)<a (?P<data>.*?)(?:<br|</p)').matches + # if match: + # for m in match: + # data += '{}{:02d}|{}|{}|'.format(m[0]+'x' if m[0] else '', int(m[1]), clean_title(m[2]), m[3]) + # + # patron = r'(?P<episode>[^|]+)\|(?P<title>[^|]+)\|(?P<data>[^|]+)\|' return locals() diff --git a/channels/vvvvid.py b/channels/vvvvid.py index c09f825b..1faadea4 100644 --- a/channels/vvvvid.py +++ b/channels/vvvvid.py @@ -24,43 +24,43 @@ except: main_host = host + '/vvvvid/ondemand/' -host = main_host +# host = main_host @support.menu def mainlist(item): if conn_id: - anime = ['anime/', - ('Popolari',['anime/', 'peliculas', 'channel/10002/last/']), - ('Nuove Uscite',['anime/', 'peliculas', 'channel/10007/last/']), - ('Generi',['anime/', 'peliculas', 'channel/10004/last/?category=']), - ('A-Z',['anime/', 'peliculas', 'channel/10003/last/?filter=']) + anime = ['/vvvvid/ondemand/anime/', + ('Popolari',['/vvvvid/ondemand/anime/', 'peliculas', 'channel/10002/last/']), + ('Nuove Uscite',['/vvvvid/ondemand/anime/', 'peliculas', 'channel/10007/last/']), + ('Generi',['/vvvvid/ondemand/anime/', 'peliculas', 'channel/10004/last/?category=']), + ('A-Z',['/vvvvid/ondemand/anime/', 'peliculas', 'channel/10003/last/?filter=']) ] - film = ['film/', - ('Popolari',['film/', 'peliculas', 'channel/10002/last/']), - ('Nuove Uscite',['film/', 'peliculas', 'channel/10007/last/']), - ('Generi',['film/', 'peliculas', 'channel/10004/last/?category=']), - ('A-Z',['film/', 'peliculas', 'channel/10003/last/?filter=']), + film = ['/vvvvid/ondemand/film/', + ('Popolari',['/vvvvid/ondemand/film/', 'peliculas', 'channel/10002/last/']), + ('Nuove Uscite',['/vvvvid/ondemand/film/', 'peliculas', 'channel/10007/last/']), + ('Generi',['/vvvvid/ondemand/film/', 'peliculas', 'channel/10004/last/?category=']), + ('A-Z',['/vvvvid/ondemand/film/', 'peliculas', 'channel/10003/last/?filter=']), ] - tvshow = ['series/', - ('Popolari',['series/', 'peliculas', 'channel/10002/last/']), - ('Nuove Uscite',['series/', 'peliculas', 'channel/10007/last/']), - ('Generi',['series/', 'peliculas', 'channel/10004/last/?category=']), - ('A-Z',['series/', 'peliculas', 'channel/10003/last/?filter=']) + tvshow = ['/vvvvid/ondemand/series/', + ('Popolari',['/vvvvid/ondemand/series/', 'peliculas', 'channel/10002/last/']), + ('Nuove Uscite',['/vvvvid/ondemand/series/', 'peliculas', 'channel/10007/last/']), + ('Generi',['/vvvvid/ondemand/series/', 'peliculas', 'channel/10004/last/?category=']), + ('A-Z',['/vvvvid/ondemand/series/', 'peliculas', 'channel/10003/last/?filter=']) ] - show = [('Show {bold} {tv}',['show/', 'peliculas', '', 'tvshow']), - ('Popolari {submenu} {tv}',['show/', 'peliculas', 'channel/10002/last/', 'tvshow']), - ('Nuove Uscite {submenu} {tv}',['show/', 'peliculas', 'channel/10007/last/', 'tvshow']), - ('Generi {submenu} {tv}',['show/', 'peliculas', 'channel/10004/last/?category=', 'tvshow']), - ('A-Z {submenu} {tv}',['show/', 'peliculas', 'channel/10003/last/?filter=', 'tvshow']), - ('Cerca Show... {bold submenu} {tv}', ['show/', 'search', '', 'tvshow']) + show = [('Show {bold} {tv}',['/vvvvid/ondemand/show/', 'peliculas', '', 'tvshow']), + ('Popolari {submenu} {tv}',['/vvvvid/ondemand/show/', 'peliculas', 'channel/10002/last/', 'tvshow']), + ('Nuove Uscite {submenu} {tv}',['/vvvvid/ondemand/show/', 'peliculas', 'channel/10007/last/', 'tvshow']), + ('Generi {submenu} {tv}',['/vvvvid/ondemand/show/', 'peliculas', 'channel/10004/last/?category=', 'tvshow']), + ('A-Z {submenu} {tv}',['/vvvvid/ondemand/show/', 'peliculas', 'channel/10003/last/?filter=', 'tvshow']), + ('Cerca Show... {bold submenu} {tv}', ['/vvvvid/ondemand/show/', 'search', '', 'tvshow']) ] - kids = [('Kids {bold}',['kids/', 'peliculas', '', 'tvshow']), - ('Popolari {submenu} {kids}',['kids/', 'peliculas', 'channel/10002/last/', 'tvshow']), - ('Nuove Uscite {submenu} {kids}',['kids/', 'peliculas', 'channel/10007/last/', 'tvshow']), - ('Generi {submenu} {kids}',['kids/', 'peliculas', 'channel/10004/last/?category=', 'tvshow']), - ('A-Z {submenu} {kids}',['kids/', 'peliculas', 'channel/10003/last/?filter=', 'tvshow']), - ('Cerca Kids... {bold submenu} {kids}', ['kids/', 'search', '', 'tvshow']) + kids = [('Kids {bold}',['/vvvvid/ondemand/kids/', 'peliculas', '', 'tvshow']), + ('Popolari {submenu} {kids}',['/vvvvid/ondemand/kids/', 'peliculas', 'channel/10002/last/', 'tvshow']), + ('Nuove Uscite {submenu} {kids}',['/vvvvid/ondemand/kids/', 'peliculas', 'channel/10007/last/', 'tvshow']), + ('Generi {submenu} {kids}',['/vvvvid/ondemand/kids/', 'peliculas', 'channel/10004/last/?category=', 'tvshow']), + ('A-Z {submenu} {kids}',['/vvvvid/ondemand/kids/', 'peliculas', 'channel/10003/last/?filter=', 'tvshow']), + ('Cerca Kids... {bold submenu} {kids}', ['/vvvvid/ondemand/kids/', 'search', '', 'tvshow']) ] else: Top = [("Visibile solo dall'Italia {bold}",[])] @@ -128,7 +128,7 @@ def peliculas(item): item.args='' make_itemlist(itemlist, item, json_file) if 'category' in item.args: - support.thumb(itemlist,genre=True) + support.thumb(itemlist,mode='genre') elif not 'filter' in item.args: if item.contentType != 'movie': autorenumber.start(itemlist) tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) diff --git a/core/autoplay.py b/core/autoplay.py index d5eace64..1894c15a 100644 --- a/core/autoplay.py +++ b/core/autoplay.py @@ -39,14 +39,14 @@ def start(itemlist, item): if not config.is_xbmc(): return itemlist - # Save the current value of "Action and Player Mode" in preferences - user_config_setting_action = config.get_setting("default_action") - # user_config_setting_player = config.get_setting("player_mode") + if config.get_setting('autoplay') or (item.channel == 'community' and item.autoplay): + # Save the current value of "Action and Player Mode" in preferences + user_config_setting_action = config.get_setting("default_action") + # user_config_setting_player = config.get_setting("player_mode") - # Enable the "View in high quality" action (if the server returns more than one quality, eg gdrive) - if not user_config_setting_action: config.set_setting("default_action", 2) + # Enable the "View in high quality" action (if the server returns more than one quality, eg gdrive) + if not user_config_setting_action: config.set_setting("default_action", 2) - if config.get_setting('autoplay'): from core.servertools import sort_servers autoplay_list = sort_servers(itemlist) @@ -142,4 +142,4 @@ def servername(server): path = filetools.join(config.get_runtime_path(), 'servers', server.lower() + '.json') name = jsontools.load(open(path, "rb").read())['name'] if name.startswith('@'): name = config.get_localized_string(int(name.replace('@',''))) - return translate_server_name(name) \ No newline at end of file + return translate_server_name(name) diff --git a/core/httptools.py b/core/httptools.py index f5df5150..2ea2dc1b 100755 --- a/core/httptools.py +++ b/core/httptools.py @@ -285,12 +285,16 @@ def downloadpage(url, **opt): parse = urlparse.urlparse(url) domain = parse.netloc - from lib import requests - session = requests.session() + if opt.get('cloudscraper'): + from lib import cloudscraper + session = cloudscraper.create_scraper() + else: + from lib import requests + session = requests.session() - if config.get_setting('resolver_dns') and not opt.get('use_requests', False): - from core import resolverdns - session.mount('https://', resolverdns.CipherSuiteAdapter(domain)) + if config.get_setting('resolver_dns') and not opt.get('use_requests', False): + from core import resolverdns + session.mount('https://', resolverdns.CipherSuiteAdapter(domain)) req_headers = default_headers.copy() diff --git a/core/item.py b/core/item.py index d3bd9156..d2982105 100644 --- a/core/item.py +++ b/core/item.py @@ -150,7 +150,7 @@ class Item(object): for k in kw: if k in ["contentTitle", "contentPlot", "contentSerieName", "show", "contentType", "contentEpisodeTitle", "contentSeason", "contentEpisodeNumber", "contentThumbnail", "plot", "duration", "contentQuality", - "quality"]: + "quality", "year"]: self.__setattr__(k, kw[k]) del kwargs[k] @@ -180,7 +180,7 @@ class Item(object): # By modifying any of these attributes content... if name in ["contentTitle", "contentPlot", "plot", "contentSerieName", "contentType", "contentEpisodeTitle", - "contentSeason", "contentEpisodeNumber", "contentThumbnail", "show", "contentQuality", "quality"]: + "contentSeason", "contentEpisodeNumber", "contentThumbnail", "show", "contentQuality", "quality", "year"]: # ...and update infoLables if name == "contentTitle": self.__dict__["infoLabels"]["title"] = value @@ -200,6 +200,8 @@ class Item(object): self.__dict__["infoLabels"]["thumbnail"] = value elif name == "contentQuality" or name == "quality": self.__dict__["infoLabels"]["quality"] = value + elif name == "year": + self.__dict__["infoLabels"]["year"] = value elif name == "duration": # String q represents the duration of the video in seconds diff --git a/core/resolverdns.py b/core/resolverdns.py index 8e87ecd2..7f22ddef 100644 --- a/core/resolverdns.py +++ b/core/resolverdns.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -import os, sys, ssl +import datetime, sys, ssl PY3 = False if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int if PY3: @@ -24,6 +24,8 @@ elif 'PROTOCOL_SSLv23' in ssl.__dict__: else: protocol = ssl.PROTOCOL_SSLv3 +current_date = datetime.datetime.now() + class CustomContext(ssl.SSLContext): def __init__(self, protocol, hostname, *args, **kwargs): @@ -54,10 +56,13 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): return self.send(request, flushedDns=True, **kwargs) def getIp(self, domain): - ip = db['dnscache'].get(domain, None) - logger.info('Cache DNS: ' + domain + ' = ' + str(ip)) + cache = db['dnscache'].get(domain, {}) + ip = None + if type(cache) != dict or (cache.get('datetime') and + current_date - cache.get('datetime') > datetime.timedelta(days=7)): + cache = None - if not ip: # not cached + if not cache: # not cached try: ip = doh.query(domain)[0] logger.info('Query DoH: ' + domain + ' = ' + str(ip)) @@ -65,11 +70,14 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): except Exception: logger.error('Failed to resolve hostname, fallback to normal dns') import traceback - logger.error(traceback.print_exc()) + logger.error(traceback.format_exc()) + else: + ip = cache.get('ip') + logger.info('Cache DNS: ' + domain + ' = ' + str(ip)) return ip def writeToCache(self, domain, ip): - db['dnscache'][domain] = ip + db['dnscache'][domain] = {'ip': ip, 'datetime': current_date} def init_poolmanager(self, *args, **kwargs): kwargs['ssl_context'] = self.ssl_context @@ -112,9 +120,9 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): request.url = urlparse.urlunparse(parse) try: ret = super(CipherSuiteAdapter, self).send(request, **kwargs) - if 400 <= ret.status_code < 500: - raise Exception - except Exception as e: + # if 400 <= ret.status_code < 500: + # raise Exception + except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError, requests.exceptions.SSLError) as e: logger.info('Request for ' + domain + ' with ip ' + ip + ' failed') logger.info(e) # if 'SSLError' in str(e): diff --git a/core/servertools.py b/core/servertools.py index f3936c33..66d01c0b 100644 --- a/core/servertools.py +++ b/core/servertools.py @@ -670,9 +670,15 @@ def sort_servers(servers_list): """ If the option "Order servers" is activated in the server configuration and there is a list of servers favorites in settings use it to sort the servers_list list - :param servers_list: List of servers to order. The items in the servers_list can be strings or Item objects. In which case it is necessary that they have an item.server attribute of type str. + :param servers_list: List of servers to order. The items in the servers_list can be strings or Item objects. In both cases it is necessary to have an item.server attribute of type str. :return: List of the same type of objects as servers_list ordered according to the favorite servers. """ + def index(lst, value): + if value in lst: + return lst.index(value) + else: + logger.debug('Index not found: ' + value) + return 999 if not servers_list: return [] @@ -683,37 +689,26 @@ def sort_servers(servers_list): servers_list = sorted(servers_list, key=lambda x: favorite_servers.index(x) if x in favorite_servers else 999) return servers_list - quality_list = ['4k', '2160p', '2160', '4k2160p', '4k2160', '4k 2160p', '4k 2160', '2k', + favorite_quality = ['4k', '2160p', '2160', '4k2160p', '4k2160', '4k 2160p', '4k 2160', '2k', 'fullhd', 'fullhd 1080', 'fullhd 1080p', 'full hd', 'full hd 1080', 'full hd 1080p', 'hd1080', 'hd1080p', 'hd 1080', 'hd 1080p', '1080', '1080p', 'hd', 'hd720', 'hd720p', 'hd 720', 'hd 720p', '720', '720p', 'hdtv', - 'sd', '480p', '480', '360p', '360', '240p', '240', - ''] + 'sd', '480p', '480', '360p', '360', '240p', '240'] sorted_list = [] - url_list_valid = [] - favorite_quality = [] + inverted = False + + if config.get_setting('default_action') == 2: + inverted = True # Priorities when ordering itemlist: - # 0: Servers and qualities - # 1: Qualities and servers - # 2: Servers only - # 3: Only qualities - # 4: Do not order + # 0: Only Qualities + # 1: Servers and Qualities + # 2: Qualities and Servers - if config.get_setting('favorites_servers') and favorite_servers and config.get_setting('default_action') and not config.get_setting('quality_priority'): - priority = 0 # Servers and qualities - elif config.get_setting('favorites_servers') and favorite_servers and config.get_setting('default_action') and config.get_setting('quality_priority'): - priority = 1 # Qualities and servers - elif config.get_setting('favorites_servers') and favorite_servers: - priority = 2 # Servers only - elif config.get_setting('default_action'): - priority = 3 # Only qualities - else: - priority = 4 # Do not order + priority = 0 + if config.get_setting('favorites_servers') and favorite_servers: priority = 1 + if config.get_setting('quality_priority'): priority = 2 - if config.get_setting('default_action') == 1: - quality_list.reverse() - favorite_quality = quality_list for item in servers_list: element = dict() @@ -724,32 +719,16 @@ def sort_servers(servers_list): if item.server.lower() in blacklisted_servers: continue - - if priority < 2: # 0: Servers and qualities or 1: Qualities and servers - element["indice_server"] = favorite_servers.index(item.server.lower()) if item.server.lower() in favorite_servers else 999 - element["indice_quality"] = favorite_quality.index(item.quality.lower()) - - elif priority == 2: # Servers only - element["indice_server"] = favorite_servers.index(item.server.lower()) - - elif priority == 3: # Only qualities - element["indice_quality"] = favorite_quality.index(item.quality.lower()) - - else: # Do not order - if item.url in url_list_valid: - continue - - element['indice_language'] = 0 if item.contentLanguage == 'ITA' else 1 - + element["index_server"] = index(favorite_servers, item.server.lower()) + element["index_quality"] = platformtools.calcResolution(item.quality) + element['index_language'] = 0 if item.contentLanguage == 'ITA' else 1 element['videoitem'] = item sorted_list.append(element) # We order according to priority - if priority == 0: sorted_list.sort(key=lambda orden: (orden['indice_language'], orden['indice_server'], orden['indice_quality'])) # Servers and qualities - elif priority == 1: sorted_list.sort(key=lambda orden: (orden['indice_language'], orden['indice_quality'], orden['indice_server'])) # Servers and qualities - elif priority == 2: sorted_list.sort(key=lambda orden: (orden['indice_language'], orden['indice_server'])) # Servers only - elif priority == 3: sorted_list.sort(key=lambda orden: (orden['indice_language'], orden['indice_quality'])) # Only qualities - else: sorted_list.sort(key=lambda orden: orden['indice_language']) + if priority == 0: sorted_list.sort(key=lambda element: (element['index_language'], -element['index_quality'] if inverted else element['index_quality'] , element['videoitem'].server)) + elif priority == 1: sorted_list.sort(key=lambda element: (element['index_language'], element['index_server'], -element['index_quality'] if inverted else element['index_quality'])) # Servers and Qualities + elif priority == 2: sorted_list.sort(key=lambda element: (element['index_language'], -element['index_quality'] if inverted else element['index_quality'], element['index_server'])) # Qualities and Servers return [v['videoitem'] for v in sorted_list if v] @@ -850,4 +829,4 @@ def translate_server_name(name): # logger.error(" %s" % message) # server_json = None # -# return server_json \ No newline at end of file +# return server_json diff --git a/core/support.py b/core/support.py index c307f96b..9202b860 100755 --- a/core/support.py +++ b/core/support.py @@ -24,6 +24,56 @@ from platformcode import config from platformcode.logger import info from platformcode import logger +channels_order = {'Rai 1': 1, + 'Rai 2': 2, + 'Rai 3': 3, + 'Rete 4': 4, + 'Canale 5': 5, + 'Italia 1': 6, + 'La7': 7, + 'NOVE': 9, + '20': 20, + 'Rai 4': 21, + 'Iris': 22, + 'Rai 5': 23, + 'Rai Movie': 24, + 'Rai Premium': 25, + 'Paramount': 27, + 'La7d': 29, + 'La 5': 30, + 'Real Time': 31, + 'Food Network': 33, + 'Cine34': 34, + 'Focus': 35, + 'Giallo': 38, + 'Top Crime': 39, + 'Boing': 40, + 'K2': 41, + 'Rai Gulp': 42, + 'Rai Yoyo': 43, + 'Frisbee': 44, + 'Cartoonito': 46, + 'Super': 46, + 'Rai News 24': 48, + 'Spike': 49, + 'TGCom': 51, + 'DMAX': 52, + 'Rai Storia': 54, + 'Mediaset Extra': 55, + 'Home and Garden TV': 56, + 'Rai Sport piu HD': 57, + 'Rai Sport': 58, + 'Motor Trend': 59, + 'Italia 2': 66, + 'VH1': 67, + 'Rai Scuola': 146, + 'Radio 105': 157, + 'R101tv': 167, + 'RMC': 256, + 'Virgin Radio': 257, + 'Rai Radio 2': 999, + } + def hdpass_get_servers(item, data=''): def get_hosts(url, quality): @@ -50,14 +100,20 @@ def hdpass_get_servers(item, data=''): url = url.replace("&download=1", "") if 'hdpass' not in url and 'hdplayer' not in url: return itemlist if not url.startswith('http'): url = 'https:' + url + item.referer = url data = httptools.downloadpage(url, CF=False).data patron_res = '<div class="buttons-bar resolutions-bar">(.*?)<div class="buttons-bar' - patron_mir = '<div class="buttons-bar hosts-bar">(.*?)<div id="main-player' + patron_mir = '<div class="buttons-bar hosts-bar">(.*?)(?:<div id="main-player|<script)' patron_option = r'<a href="([^"]+?)"[^>]+>([^<]+?)</a' res = scrapertools.find_single_match(data, patron_res) + # non threaded for webpdb + # for res_url, res_video in scrapertools.find_multiple_matches(res, patron_option): + # res_url = scrapertools.decodeHtmlentities(res_url) + # itemlist.extend(get_hosts(res_url, res_video)) + # with futures.ThreadPoolExecutor() as executor: thL = [] for res_url, res_video in scrapertools.find_multiple_matches(res, patron_option): @@ -69,8 +125,8 @@ def hdpass_get_servers(item, data=''): return server(item, itemlist=itemlist) + def hdpass_get_url(item): - item.referer = item.url data = httptools.downloadpage(item.url, CF=False).data src = scrapertools.find_single_match(data, r'<iframe allowfullscreen custom-src="([^"]+)') if src: item.url = base64.b64decode(src) @@ -78,6 +134,7 @@ def hdpass_get_url(item): item.url, c = unshortenit.unshorten_only(item.url) return [item] + def color(text, color): return "[COLOR " + color + "]" + text + "[/COLOR]" @@ -224,6 +281,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t scraped[kk] = val.strip() if type(val) == str else val # episode = re.sub(r'\s-\s|-|x|–|×', 'x', scraped['episode']) if scraped['episode'] else '' + title = cleantitle(scraped.get('title', '')) if group and scraped.get('title', '') in contents and not item.grouped: # same title and grouping enabled continue @@ -371,22 +429,23 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t title = title, fulltitle = item.fulltitle if function == 'episodios' else title, show=item.show if function == 'episodios' else title, - quality = quality, - url = scraped["url"] if scraped["url"] else item.url, - infoLabels = infolabels, - thumbnail = item.prevthumb if item.prevthumb else item.thumbnail if not scraped["thumb"] else scraped["thumb"], - args = item.args, - contentSerieName = title if 'movie' not in [contentType] and function != 'episodios' else item.contentSerieName, - contentTitle = title if 'movie' in [contentType] and function == 'peliculas' else item.contentTitle, - contentLanguage = lang1 if lang1 else item.contentLanguage, - contentSeason = infolabels.get('season', ''), + quality=quality, + url=scraped["url"] if scraped["url"] else item.url, + infoLabels=infolabels, + thumbnail=item.prevthumb if item.prevthumb else item.thumbnail if not scraped["thumb"] else scraped["thumb"], + args=item.args, + contentSerieName= title if contentType not in ['movie'] and function != 'episodios' or contentType in ['undefined'] else item.contentSerieName, + contentTitle= title if contentType in ['movie', 'undefined'] and function == 'peliculas' else item.contentTitle, + contentLanguage = lang1, + contentSeason= infolabels.get('season', ''), contentEpisodeNumber=infolabels.get('episode', ''), news = item.news if item.news else '', other = scraped['other'] if scraped['other'] else '', grouped = group, title2 = cleantitle(title2) if title2 else '', episode2 = second_episode, - extraInfo = extraInfo + extraInfo = extraInfo, + disable_videolibrary = not args.get('addVideolibrary', True) ) if scraped['episode'] and group and not item.grouped: # some adjustment for grouping feature @@ -570,7 +629,7 @@ def scrape(func): download(itemlist, item, function=function) if 'patronGenreMenu' in args and itemlist: - itemlist = thumb(itemlist, genre=True) + itemlist = thumb(itemlist, mode='genre') if 'patronMenu' in args and itemlist: itemlist = thumb(itemlist) @@ -777,11 +836,13 @@ def menu(func): for name, var in args.items(): if name not in listUrls and name != 'item': listUrls_extra.append(name) + for name in listUrls_extra: dictUrl[name] = args.get(name, None) for sub, var in dictUrl[name]: + # sub = scrapertools.unescape(sub) menuItem(itemlist, filename, - title = sub + ' ', + title = sub, url = host + var[0] if len(var) > 0 else '', action = var[1] if len(var) > 1 else 'peliculas', args=var[2] if len(var) > 2 else '', @@ -791,8 +852,6 @@ def menu(func): menuItem(itemlist, filename, config.get_localized_string(70741) % '… {bold}', 'search', host + dictUrl['search'], style=not global_search) if not global_search: - # autoplay.init(item.channel, list_servers, list_quality) - # autoplay.show_option(item.channel, itemlist) channel_config(item, itemlist) # Apply auto Thumbnails at the menus @@ -1153,6 +1212,7 @@ def nextPage(itemlist, item, data='', patron='', function_or_level=1, next_page= thumbnail=thumb())) return itemlist[-1] + def pagination(itemlist, item, page, perpage, function_level=1): if len(itemlist) >= page * perpage: itemlist.append( @@ -1364,7 +1424,7 @@ def addQualityTag(item, itemlist, data, patron): def get_jwplayer_mediaurl(data, srvName, onlyHttp=False, dataIsBlock=False): from core import jsontools video_urls = [] - block = scrapertools.find_single_match(data, r'sources:\s*([^\]]+\])') if not dataIsBlock else data + block = scrapertools.find_single_match(data, r'sources"?\s*:\s*(.*?}])') if not dataIsBlock else data if block: json = jsontools.load(block) if json: @@ -1385,20 +1445,19 @@ def get_jwplayer_mediaurl(data, srvName, onlyHttp=False, dataIsBlock=False): for url, quality in sources: quality = 'auto' if not quality else quality if url.split('.')[-1] != 'mpd': - video_urls.append(['.' + url.split('.')[-1] + ' [' + quality + '] [' + srvName + ']', url if not onlyHttp else url.replace('https://', 'http://')]) + video_urls.append(['.' + url.split('.')[-1].split('?')[0] + ' [' + quality + '] [' + srvName + ']', url.replace(' ', '%20') if not onlyHttp else url.replace('https://', 'http://')]) video_urls.sort(key=lambda x: x[0].split()[1]) return video_urls -def thumb(data=None, genre=False, live=False): +def thumb(data=None, mode=None): ''' data = str, item or itemlist - genre = bool, search icon in genres - live = bool, add icon by channel name + mode = str, genre, live, quality ''' - if live: + if mode == 'live': if type(data) == list: for item in data: item.thumbnail = "https://raw.githubusercontent.com/kodiondemand/media/master/live/" + item.fulltitle.lower().replace(' ','_') + '.png' @@ -1454,12 +1513,18 @@ def thumb(data=None, genre=False, live=False): _romance = ['romantico', 'sentimentale', 'romance', 'soap'] _family = ['famiglia','famiglie', 'family'] _historical = ['storia', 'storico', 'history', 'historical'] - _hd = ['hd','altadefinizione','alta', '1080', '1080p', 'fullhd'] - _4k = ['4k'] _setting = ['impostazioni', 'settaggi', 'configura', 'configurare', 'gestire', 'gestisci', 'gestione', 'setting', 'config'] _talk = ['talk'] _reality = ['reality'] _quality = ['qualità', 'risoluzione', 'risoluzioni', 'quality', 'resolution', 'resolutions'] + _cam = ['cam'] + _ts = ['ts'] + _md = ['md'] + _sd = ['sd'] + _hd = ['hd'] + _fhd = ['fullhd'] + _2k = ['2k'] + _4k = ['4k'] main_dict = {'movie':_movie, 'tvshow':_tvshow, @@ -1491,6 +1556,7 @@ def thumb(data=None, genre=False, live=False): 'family':_family, 'teenager':_teenager, 'learning':_learning, + 'quality':_quality, 'autoplay':[config.get_localized_string(60071)] } @@ -1524,7 +1590,15 @@ def thumb(data=None, genre=False, live=False): 'reality':_reality, 'tvmovie':_movie} - suffix_dict = {'_hd':_hd, + search = ['cerca', 'cercare', 'ricerca', 'ricercare', 'trova', 'trovare', 'search', 'searching', 'find', 'finding'] + + suffix_dict = {'_cam':_cam, + '_ts':_ts, + '_md':_md, + '_sd':_sd, + '_hd':_hd, + '_fullhd':_fhd, + '_2k':_2k, '_4k':_4k, '_az':_az, '_genre':_genre, @@ -1536,38 +1610,41 @@ def thumb(data=None, genre=False, live=False): '_sub':_sub, '_ita':_ita, '_quality':_quality, - '_cinema':_cinema} + '_cinema':_cinema, + '_search':search} - search = ['cerca', 'cercare', 'ricerca', 'ricercare', 'trova', 'trovare', 'search', 'searching', 'find', 'finding'] + quality_dict = {'cam':_cam, + 'ts':_ts, + 'md':_md, + 'sd':_sd, + 'hd':_hd, + 'fhd':_fhd, + '2k':_2k, + '4k':_4k} - search_suffix ={'_movie':_movie, - '_tvshow':_tvshow, - '_anime':_anime, - '_year':_year, + search_suffix ={'_year':_year, '_top':_top, - '_documentary':_documentary, '_music':_music, '_star':_star, '_genre':_genre, '_top':_top} - def autoselect_thumb(item, genre): + def autoselect_thumb(item, mode): searched_title = re.split(r'\.|\{|\}|\(|\)|/| ', scrapertools.unescape(re.sub('\[[^\]]*\]||\u2026|\u2022','', item.title.lower()))) logger.debug('SEARCED', searched_title) thumb = '' - if genre: + if mode == 'genre': for t, titles in genre_dict.items(): - if any(word in searched_title for word in titles ): + if any(word in searched_title for word in titles): + thumb = t + elif mode == 'quality': + for t, titles in quality_dict.items(): + if searched_title[0] in titles: thumb = t else: if any(word in searched_title for word in _setting): thumb = 'setting' - elif any(word in searched_title for word in search): - thumb = 'search' - for suffix, titles in search_suffix.items(): - if any(word in searched_title for word in titles): - thumb = thumb + suffix - if not thumb: + else: for t, titles in main_dict.items(): if any(word in searched_title for word in titles): thumb = t @@ -1575,6 +1652,12 @@ def thumb(data=None, genre=False, live=False): for suffix, titles in suffix_dict.items(): if any(word in searched_title for word in titles): thumb = t + suffix + if not thumb: + if any(word in searched_title for word in search): + thumb = 'search' + for suffix, titles in search_suffix.items(): + if any(word in searched_title for word in titles): + thumb = thumb + suffix if not thumb: for t, titles in icon_dict.items(): if any(word in searched_title for word in titles): @@ -1587,7 +1670,7 @@ def thumb(data=None, genre=False, live=False): if data: if type(data) == list: for item in data: - autoselect_thumb(item, genre) + autoselect_thumb(item, mode) return data elif type(data) == str: @@ -1595,7 +1678,7 @@ def thumb(data=None, genre=False, live=False): if not file_extension: data += '.png' return get_thumb(data) else: - return autoselect_thumb(data, genre) + return autoselect_thumb(data, mode) else: return get_thumb('next.png') @@ -1610,4 +1693,4 @@ def get_thumb(thumb_name, view="thumb_"): else: icon_pack_name = config.get_setting('icon_set', default="default") media_path = filetools.join("https://raw.githubusercontent.com/kodiondemand/media/master/themes/new", icon_pack_name) - return filetools.join(media_path, thumb_name) \ No newline at end of file + return filetools.join(media_path, thumb_name) diff --git a/core/tmdb.py b/core/tmdb.py index 08e110a1..4d7c466c 100644 --- a/core/tmdb.py +++ b/core/tmdb.py @@ -606,6 +606,8 @@ def discovery(item, dict_=False, cast=False): from core.item import Item if dict_: + if item.page: + item.discovery['page'] = item.page listado = Tmdb(discover = dict_, cast=cast) elif item.search_type == 'discover': @@ -1029,7 +1031,10 @@ class Tmdb(object): # We sort result based on fuzzy match to detect most similar if len(results) > 1: from lib.fuzzy_match import algorithims - results.sort(key=lambda r: algorithims.trigram(text_simple, r.get('name', '') if self.search_type == 'tv' else r.get('title', '')), reverse=True) + if self.search_type == 'multi': + results.sort(key=lambda r: algorithims.trigram(text_simple, r.get('name', '') if r.get('media_type') == 'tv' else r.get('title', '')), reverse=True) + else: + results.sort(key=lambda r: algorithims.trigram(text_simple, r.get('name', '') if self.search_type == 'tv' else r.get('title', '')), reverse=True) # We return the number of results of this page self.results = results @@ -1539,10 +1544,12 @@ class Tmdb(object): :rtype: list of Dict """ ret = [] + if self.result['id']: if self.result['videos']: self.result["videos"] = self.result["videos"]['results'] else: + self.result["videos"] = [] # First video search in the search language url = "{}/{}/{}/videos?api_key={}&language={}".format(host, self.search_type, self.result['id'], api, self.search_language) @@ -1638,7 +1645,10 @@ class Tmdb(object): if v == "None": continue - if k == 'overview': + if k == 'media_type': + ret_infoLabels['mediatype'] = 'tvshow' if v == 'tv' else 'movie' + + elif k == 'overview': if origen: ret_infoLabels['plot'] = v else: diff --git a/core/trakt_tools.py b/core/trakt_tools.py index f1fb8aca..bf00588a 100644 --- a/core/trakt_tools.py +++ b/core/trakt_tools.py @@ -26,7 +26,7 @@ def auth_trakt(): post = {'client_id': client_id} post = jsontools.dump(post) # Se solicita url y código de verificación para conceder permiso a la app - url = "http://api-v2launch.trakt.tv/oauth/device/code" + url = "http://api.trakt.tv/oauth/device/code" data = httptools.downloadpage(url, post=post, headers=headers).data data = jsontools.load(data) item.verify_url = data["verification_url"] @@ -57,14 +57,14 @@ def token_trakt(item): try: if item.extra == "renew": refresh = config.get_setting("refresh_token_trakt", "trakt") - url = "http://api-v2launch.trakt.tv/oauth/device/token" + url = "http://api.trakt.tv/oauth/device/token" post = {'refresh_token': refresh, 'client_id': client_id, 'client_secret': client_secret, 'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', 'grant_type': 'refresh_token'} post = jsontools.dump(post) data = httptools.downloadpage(url, post=post, headers=headers).data data = jsontools.load(data) elif item.action == "token_trakt": - url = "http://api-v2launch.trakt.tv/oauth/device/token" + url = "http://api.trakt.tv/oauth/device/token" post = "code=%s&client_id=%s&client_secret=%s" % (item.device_code, client_id, client_secret) data = httptools.downloadpage(url, post=post, headers=headers).data data = jsontools.load(data) @@ -83,7 +83,7 @@ def token_trakt(item): config.set_setting("trakt_sync", False) return - url = "http://api-v2launch.trakt.tv/oauth/device/token" + url = "http://api.trakt.tv/oauth/device/token" post = {'code': item.device_code, 'client_id': client_id, 'client_secret': client_secret} post = jsontools.dump(post) data = httptools.downloadpage(url, post=post, headers=headers).data diff --git a/core/videolibrarytools.py b/core/videolibrarytools.py index 934de5f2..cbc4fd38 100644 --- a/core/videolibrarytools.py +++ b/core/videolibrarytools.py @@ -691,6 +691,14 @@ def add_to_videolibrary(item, channel): platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(70838) % item.contentTitle) +def add_to_videolibrary(item, channel): + itemlist = getattr(channel, item.from_action)(item) + if itemlist and itemlist[0].contentType == 'episode': + return add_tvshow(item, channel, itemlist) + else: + return add_movie(item) + + def add_movie(item): """ Keep a movie at the movie library. The movie can be a link within a channel or a previously downloaded video. @@ -757,6 +765,7 @@ def add_tvshow(item, channel=None, itemlist=[]): @param channel: channel from which the series will be saved. By default, item.from_channel or item.channel will be imported. """ + logger.debug("show=#" + item.show + "#") item.contentType = 'tvshow' # from platformcode.launcher import set_search_temp; set_search_temp(item) diff --git a/lib/proxytranslate.py b/lib/proxytranslate.py index c0871d5f..47be03b9 100644 --- a/lib/proxytranslate.py +++ b/lib/proxytranslate.py @@ -11,28 +11,26 @@ else: import re import time - import requests try: from platformcode import logger except ImportError: logger = None -HEADERS = { - 'Host': 'translate.google.com', - 'User-Agent': 'android' -} +HEADERS = {'User-Agent': 'android', + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "Accept-Language": "it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Charset": "UTF-8", + "Accept-Encoding": "gzip"} -MAX_CONECTION_THREAD = 10 SL = 'en' TL = 'it' BASE_URL_PROXY = 'https://translate.googleusercontent.com' -BASE_URL_TRANSLATE = 'https://translate.google.com/translate?hl=it&sl=' + SL + '&tl=' + TL + '&u=[TARGET_URL]&sandbox=0' # noqa: E501 +BASE_URL_TRANSLATE = 'https://translate.google.com/translate?hl=it&sl=' + SL + '&tl=' + TL + '&u=[TARGET_URL]' # noqa: E501 def checker_url(html, url): - grep_regex = re.findall(r'(?:href="|src="|value=")([^"]+)', html) # noqa: E501 + grep_regex = re.findall(r'(?:href="|src="|value=")(https?://translate[^"]+)', html) # noqa: E501 for url_result_regex in grep_regex: if url in url_result_regex: return url_result_regex.replace('&', '&') @@ -44,6 +42,8 @@ def process_request_proxy(url): try: domain = urlparse.urlparse(url).netloc + session = requests.Session() + session.headers.update(HEADERS) target_url = \ BASE_URL_TRANSLATE.replace('[TARGET_URL]', request.quote(url)) @@ -53,7 +53,7 @@ def process_request_proxy(url): else: print(target_url) - return_html = requests.get(target_url, timeout=20, headers=HEADERS) + return_html = session.get(target_url, timeout=20) if not return_html: return @@ -68,10 +68,9 @@ def process_request_proxy(url): else: print(url_request) - request_final = requests.get( + request_final = session.get( url_request, - timeout=20, - headers={'User-Agent': 'android'} + timeout=20 ) url_request_proxy = checker_url( @@ -86,10 +85,9 @@ def process_request_proxy(url): result = None while not data or 'Sto traducendo' in data: time.sleep(0.5) - result = requests.get( + result = session.get( url_request_proxy, timeout=20 - # headers={'User-Agent': 'android'} ) data = result.content.decode('utf-8', 'ignore') if not PY3: @@ -99,7 +97,7 @@ def process_request_proxy(url): data = re.sub('\s(\w+)=(?!")([^<>\s]+)', r' \1="\2"', data) data = re.sub('https://translate\.googleusercontent\.com/.*?u=(.*?)&usg=[A-Za-z0-9_-]+', '\\1', data) - data = re.sub('https?://[a-zA-Z0-9-]+' + domain.replace('.', '-') + '\.translate\.goog(/[a-zA-Z0-9#/-]+)', 'https://' + domain + '\\1', data) + data = re.sub('https?://[a-zA-Z0-9-]*' + domain.replace('.', '-') + '\.translate\.goog(/[a-zA-Z0-9#/-]+)', 'https://' + domain + '\\1', data) data = re.sub('\s+<', '<', data) data = data.replace('&', '&').replace('https://translate.google.com/website?sl=' + SL + '&tl=' + TL + '&ajax=1&u=', '') diff --git a/lib/unshortenit.py b/lib/unshortenit.py index a21783df..b9f78684 100644 --- a/lib/unshortenit.py +++ b/lib/unshortenit.py @@ -45,7 +45,7 @@ class UnshortenIt(object): # for services that only include real link inside iframe _simple_iframe_regex = r'cryptmango|xshield\.net|vcrypt\.club' # for services that only do redirects - _simple_redirect = r'streamcrypt\.net/[^/]+' + _simple_redirect = r'streamcrypt\.net/[^/]+|uprot\.net|is\.gd' listRegex = [_adfly_regex, _linkbucks_regex, _adfocus_regex, _lnxlu_regex, _shst_regex, _hrefli_regex, _anonymz_regex, _shrink_service_regex, _rapidcrypt_regex, _simple_iframe_regex, _linkup_regex, _linkhub_regex, @@ -59,6 +59,7 @@ class UnshortenIt(object): def unshorten(self, uri, type=None): code = 0 while True: + uri = uri.strip() oldUri = uri domain = urlsplit(uri).netloc if not domain: diff --git a/lib/urllib3/util/request.py b/lib/urllib3/util/request.py index 262a6d61..cb2cac6d 100644 --- a/lib/urllib3/util/request.py +++ b/lib/urllib3/util/request.py @@ -52,7 +52,7 @@ def make_headers( Example:: - >>> make_headers(keep_alive=True, user_agent="Batman/1.0") + >>> make_headers(keep_amode='live', user_agent="Batman/1.0") {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} >>> make_headers(accept_encoding=True) {'accept-encoding': 'gzip,deflate'} diff --git a/platformcode/autorenumber.py b/platformcode/autorenumber.py index 7f38e5f8..b9aa0b23 100644 --- a/platformcode/autorenumber.py +++ b/platformcode/autorenumber.py @@ -136,11 +136,12 @@ class autorenumber(): else: self.renumberdict = {} for item in self.itemlist: - item.context = [{"title": typo(config.get_localized_string(70585), 'bold'), - "action": "start", - "channel": "autorenumber", - "from_channel": item.channel, - "from_action": item.action}] + if item.contentType != 'movie': + item.context = [{"title": typo(config.get_localized_string(70585), 'bold'), + "action": "start", + "channel": "autorenumber", + "from_channel": item.channel, + "from_action": item.action}] def config(self): # Pulizia del Titolo @@ -149,16 +150,18 @@ class autorenumber(): elif not self.item.infoLabels['tmdb_id']: self.item.contentSerieName = self.title.rstrip('123456789 ') - self.item.infoLabels['imdb_id'] = '' - self.item.infoLabels['tvdb_id'] = '' - self.item.infoLabels['tmdb_id'] = '' - self.item.infoLabels['year'] = '-' self.item.contentType = 'tvshow' - while not self.item.exit: - tmdb.find_and_set_infoLabels(self.item) - if self.item.infoLabels['tmdb_id']: self.item.exit = True - else:self.item = platformtools.dialog_info(self.item, 'tmdb') + if not self.item.disabletmdb: + self.item.infoLabels['imdb_id'] = '' + self.item.infoLabels['tvdb_id'] = '' + self.item.infoLabels['tmdb_id'] = '' + self.item.infoLabels['year'] = '-' + + while not self.item.exit: + tmdb.find_and_set_infoLabels(self.item) + if self.item.infoLabels['tmdb_id']: self.item.exit = True + else:self.item = platformtools.dialog_info(self.item, 'tmdb') # Rinumerazione Automatica if (not self.id and self.auto) or self.item.setrenumber: diff --git a/platformcode/backup.py b/platformcode/backup.py index e9596559..bf86b9d6 100644 --- a/platformcode/backup.py +++ b/platformcode/backup.py @@ -3,7 +3,7 @@ # Backup and restore video library # ------------------------------------------------------------ -import datetime, xbmc, os, shutil +import datetime, xbmc, os, shutil, sys from zipfile import ZipFile from core import videolibrarytools, filetools @@ -11,12 +11,15 @@ from platformcode import logger, config, platformtools, xbmc_videolibrary from distutils.dir_util import copy_tree from specials import videolibrary -temp_path = u'' + xbmc.translatePath("special://userdata/addon_data/plugin.video.kod/temp/") -videolibrary_temp_path = u'' + xbmc.translatePath("special://userdata/addon_data/plugin.video.kod/temp/videolibrary") -movies_path = u'' + filetools.join(videolibrary_temp_path, "movies") -tvshows_path = u'' + filetools.join(videolibrary_temp_path, "tvshows") -videolibrary_movies_path = u'' + videolibrarytools.MOVIES_PATH -videolibrary_tvshows_path = u'' + videolibrarytools.TVSHOWS_PATH +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + +temp_path = unicode(xbmc.translatePath("special://userdata/addon_data/plugin.video.kod/temp/")) +videolibrary_temp_path = unicode(xbmc.translatePath("special://userdata/addon_data/plugin.video.kod/temp/videolibrary")) +movies_path = unicode(filetools.join(videolibrary_temp_path, "movies")) +tvshows_path = unicode(filetools.join(videolibrary_temp_path, "tvshows")) +videolibrary_movies_path = unicode(videolibrarytools.MOVIES_PATH) +videolibrary_tvshows_path = unicode(videolibrarytools.TVSHOWS_PATH) def export_videolibrary(item): @@ -25,7 +28,7 @@ def export_videolibrary(item): zip_file_folder = platformtools.dialog_browse(3, config.get_localized_string(80002)) if zip_file_folder == "": return - zip_file = u'' + xbmc.translatePath(zip_file_folder + "KoD_video_library-" + str(datetime.date.today()) + ".zip") + zip_file = unicode(xbmc.translatePath(zip_file_folder + "KoD_video_library-" + str(datetime.date.today()) + ".zip")) p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(80003)) # p_dialog.update(0) @@ -53,7 +56,7 @@ def export_videolibrary(item): def import_videolibrary(item): logger.info() - zip_file = u'' + platformtools.dialog_browse(1, config.get_localized_string(80005), mask=".zip") + zip_file = unicode(platformtools.dialog_browse(1, config.get_localized_string(80005), mask=".zip")) if zip_file == "": return if not platformtools.dialog_yesno(config.get_localized_string(20000), config.get_localized_string(80006)): @@ -112,6 +115,7 @@ def zip(dir, file): if smb: filetools.move(file, temp) + def unzip(dir, file): if file.lower().startswith('smb://'): temp = filetools.join(temp_path, os.path.split(file)[-1]) diff --git a/platformcode/contextmenu/contextmenu.json b/platformcode/contextmenu/contextmenu.json index 0bd8617f..3acd6121 100644 --- a/platformcode/contextmenu/contextmenu.json +++ b/platformcode/contextmenu/contextmenu.json @@ -1,5 +1,5 @@ [ "platformcode.contextmenu.search", - "platformcode.contextmenu.update_tv_show", + "platformcode.contextmenu.tvshow_options", "platformcode.contextmenu.trailer" ] \ No newline at end of file diff --git a/platformcode/contextmenu/update_tv_show.py b/platformcode/contextmenu/update_tv_show.py deleted file mode 100644 index d4675ee0..00000000 --- a/platformcode/contextmenu/update_tv_show.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -import xbmc, sys, xbmcgui, os, xbmcvfs, traceback -from platformcode import config, logger - -librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) -sys.path.insert(0, librerias) - -from core.item import Item -from lib.sambatools import libsmb as samba -from core import scrapertools, support - -path = '' -mediatype = '' - - -def exists(path, silent=False, vfs=True): - path = xbmc.translatePath(path) - try: - if vfs: - result = bool(xbmcvfs.exists(path)) - if not result and not path.endswith('/') and not path.endswith('\\'): - result = bool(xbmcvfs.exists(join(path, ' ').rstrip())) - return result - elif path.lower().startswith("smb://"): - return samba.exists(path) - else: - return os.path.exists(path) - except: - logger.error("ERROR when checking the path: %s" % path) - if not silent: - logger.error(traceback.format_exc()) - return False - - -def join(*paths): - list_path = [] - if paths[0].startswith("/"): - list_path.append("") - for path in paths: - if path: - list_path += path.replace("\\", "/").strip("/").split("/") - - if scrapertools.find_single_match(paths[0], r'(^\w+:\/\/)'): - return str("/".join(list_path)) - else: - return str(os.sep.join(list_path)) - - -def search_paths(Id): - records = execute_sql('SELECT idPath FROM tvshowlinkpath WHERE idShow LIKE "%s"' % Id) - if len(records) >= 1: - for record in records: - path_records = execute_sql('SELECT strPath FROM path WHERE idPath LIKE "%s"' % record[0]) - for path in path_records: - if config.get_setting('videolibrarypath') in path[0] and exists(join(path[0], 'tvshow.nfo')): - return path[0] - return '' - - -def execute_sql(sql): - logger.debug() - file_db = "" - records = None - - # We look for the archive of the video database according to the version of kodi - video_db = config.get_platform(True)['video_db'] - if video_db: - file_db = os.path.join(xbmc.translatePath("special://userdata/Database"), video_db) - - # alternative method to locate the database - if not file_db or not os.path.exists(file_db): - file_db = "" - for f in os.path.listdir(xbmc.translatePath("special://userdata/Database")): - path_f = os.path.join(xbmc.translatePath("special://userdata/Database"), f) - - if os.path.pathoos.pathols.isfile(path_f) and f.lower().startswith('myvideos') and f.lower().endswith('.db'): - file_db = path_f - break - - if file_db: - logger.debug("DB file: %s" % file_db) - conn = None - try: - import sqlite3 - conn = sqlite3.connect(file_db) - cursor = conn.cursor() - - logger.debug("Running sql: %s" % sql) - cursor.execute(sql) - conn.commit() - - records = cursor.fetchall() - if sql.lower().startswith("select"): - if len(records) == 1 and records[0][0] is None: - records = [] - - conn.close() - logger.debug("Query executed. Records: %s" % len(records)) - - except: - logger.error("Error executing sql query") - if conn: - conn.close() - - else: - logger.debug("Database not found") - - return records - - -def get_id(): - global mediatype - - mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') - if mediatype == 'tvshow': - dbid = xbmc.getInfoLabel('ListItem.DBID') - elif mediatype in ('season', 'episode'): - dbid = xbmc.getInfoLabel('ListItem.TvShowDBID') - else: - dbid = '' - return dbid - -def check_condition(): - # support.dbg() - global path - path = search_paths(get_id()) - return path - - -def get_menu_items(): - logger.debug('get menu item') - if check_condition(): - items = [(config.get_localized_string(70269), update)] - from core.videolibrarytools import read_nfo - nfo = path + 'tvshow.nfo' - item = read_nfo(nfo)[1] - if item: - item.nfo = nfo - item_url = item.tourl() - # Context menu: Automatically search for new episodes or not - if item.active and int(item.active) > 0: - update_text = config.get_localized_string(60022) - value = 0 - else: - update_text = config.get_localized_string(60023) - value = 1 - items.append((update_text, lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&title={}&action=mark_tvshow_as_updatable&channel=videolibrary&active={})".format(item_url, update_text, str(value))))) - if item.local_episodes_path == "": - items.append((config.get_localized_string(80048), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&action=add_local_episodes&channel=videolibrary&path={})".format(item_url, path)))) - - return items - else: - return [] - - -def update(): - dbid = get_id() - path = search_paths(dbid) - if path: - item = Item(action="update_tvshow", channel="videolibrary", path=path) - # Why? I think it is not necessary, just commented - # item.tourl() - xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")") diff --git a/platformcode/keymaptools.py b/platformcode/keymaptools.py index 34b8e014..ac98cfac 100644 --- a/platformcode/keymaptools.py +++ b/platformcode/keymaptools.py @@ -10,12 +10,14 @@ import channelselector addon_icon = filetools.join( config.__settings__.getAddonInfo( "path" ),'resources', 'media', 'logo.png' ) background = 'FF232323' +overlay = '77232323' text = 'FFFFFFFF' select = 'FF0082C2' if config.get_setting('icon_set') == 'dark': background = 'FFDCDCDC' + overlay = '77DCDCDC' text = 'FF232323' - select = '880082C2' + select = 'FF78BDDF' class KeyListener(xbmcgui.WindowXMLDialog): TIMEOUT = 10 @@ -122,13 +124,15 @@ class Main(xbmcgui.WindowXMLDialog): def menulist(self, menu): itemlist = [] + self.getControl(200).setLabel(background) + self.getControl(201).setLabel(overlay) + self.getControl(202).setLabel(select) + self.getControl(203).setLabel(text) for menuentry in menu: # if not menuentry.channel: menuentry.channel = 'news' + title = re.sub(r'(\[[/]?COLOR[^\]]*\])','',menuentry.title) item = xbmcgui.ListItem(title) - item.setProperty('background', background) - item.setProperty('text', text) - item.setProperty('select', select) item.setProperty('channel', menuentry.channel) item.setProperty('focus', '0') item.setProperty('thumbnail', menuentry.thumbnail) @@ -175,6 +179,7 @@ class Main(xbmcgui.WindowXMLDialog): def submenu(self): + itmlist = [] channel_name = self.MENU.getSelectedItem().getProperty('channel') focus = int(self.MENU.getSelectedItem().getProperty('focus')) if channel_name == 'channelselector': diff --git a/platformcode/launcher.py b/platformcode/launcher.py index a581b74c..675f0d6b 100644 --- a/platformcode/launcher.py +++ b/platformcode/launcher.py @@ -5,11 +5,12 @@ from specials import videolibrary import sys, os + PY3 = False if sys.version_info[0] >= 3:PY3 = True; unicode = str; unichr = chr; long = int from core.item import Item -from core import filetools, jsontools, videolibrarydb +from core import filetools, videolibrarydb from platformcode import config, logger, platformtools from platformcode.logger import WebErrorException temp_search_file = config.get_temp_file('temp-search') @@ -144,14 +145,20 @@ def run(item=None): if not webbrowser.open(item.url): import xbmc if xbmc.getCondVisibility('system.platform.linux') and xbmc.getCondVisibility('system.platform.android'): # android - xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % (item.url)) + xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % item.url) else: - try: - import urllib.request as urllib - except ImportError: - import urllib - short = urllib.urlopen('https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read().decode('utf-8') - platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % short) + platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % "\n".join([item.url[j:j+57] for j in range(0, len(item.url), 57)])) + elif item.action == "gotopage": + page = platformtools.dialog_numeric(0, config.get_localized_string(70513)) + if page: + import xbmc + item.action = item.real_action + if item.page: + item.page = page + else: + import re + item.url = re.sub('([=/])[0-9]+(/?)$', '\g<1>' + page + '\g<2>', item.url) + xbmc.executebuiltin("Container.Update(%s?%s)" % (sys.argv[0], item.tourl())) else: # Checks if channel exists if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")): @@ -251,6 +258,11 @@ def run(item=None): from core import videolibrarytools videolibrarytools.add_to_videolibrary(item, channel) + # Special action for adding a undefined to the library + elif item.action == "add_to_library": + from core import videolibrarytools + videolibrarytools.add_to_videolibrary(item, channel) + # Special action for downloading all episodes from a serie elif item.action == "download_all_episodes": from specials import downloads diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index b2541c52..a0a2261a 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -416,15 +416,18 @@ def render_items(itemlist, parent_item): context_commands = def_context_commands listitem.addContextMenuItems(context_commands) return item, item_url, listitem - # from core.support import dbg;dbg() - r_list = [set_item(i, item, parent_item) for i, item in enumerate(itemlist)] - # r_list = [] - # with futures.ThreadPoolExecutor() as executor: - # searchList = [executor.submit(set_item, i, item, parent_item) for i, item in enumerate(itemlist)] - # for res in futures.as_completed(searchList): - # r_list.append(res.result()) - # r_list.sort(key=lambda it: it[0].itemlistPosition) + # For Debug + # from core.support import dbg;dbg() + # r_list = [set_item(i, item, parent_item) for i, item in enumerate(itemlist)] + + r_list = [] + + with futures.ThreadPoolExecutor() as executor: + searchList = [executor.submit(set_item, i, item, parent_item) for i, item in enumerate(itemlist)] + for res in futures.as_completed(searchList): + r_list.append(res.result()) + r_list.sort(key=lambda it: it[0].itemlistPosition) for item, item_url, listitem in r_list: dirItems.append(('%s?%s' % (sys.argv[0], item_url), listitem, item.folder, len(r_list))) @@ -435,7 +438,7 @@ def render_items(itemlist, parent_item): elif parent_item.sorted == 'name':xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE) if parent_item.list_type == '': - breadcrumb = parent_item.category.capitalize() + breadcrumb = parent_item.category #.capitalize() else: if 'similar' in parent_item.list_type: if parent_item.contentTitle != '': @@ -682,7 +685,7 @@ def set_context_commands(item, item_url, parent_item, **kwargs): context_commands.append((config.get_localized_string(60350), "Container.Refresh (%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': 'search', 'action': "from_context", 'from_channel': item.channel, 'contextual': True, 'text': item.wanted})))) context_commands.append( (config.get_localized_string(70561), "Container.Update (%s?%s&%s)" % (sys.argv[0], item_url, 'channel=search&action=from_context&search_type=list&page=1&list_type=%s/%s/similar' % (mediatype, item.infoLabels['tmdb_id'])))) - if item.channel != "videolibrary" and item.videolibrary != False: + if item.channel != "videolibrary" and item.videolibrary != False and not item.disable_videolibrary: # Add Series to the video library if item.action in ["episodios", "get_episodios", "get_seasons"] and item.contentSerieName: context_commands.append((config.get_localized_string(60352), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_serie_to_library&from_action={}&contentChannel=videolibrary'.format(item.action)))) @@ -692,7 +695,7 @@ def set_context_commands(item, item_url, parent_item, **kwargs): elif item.action in ['check'] and item.contentTitle or item.contentSerieName: context_commands.append((config.get_localized_string(30161), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_to_library&from_action={}&contentChannel=videolibrary'.format(item.action)))) - if not item.local and item.channel not in ["downloads", "filmontv", "search"] and item.server != 'torrent' and parent_item.action != 'mainlist' and config.get_setting('downloadenabled'): + if not item.local and item.channel not in ["downloads", "filmontv", "search"] and item.server != 'torrent' and parent_item.action != 'mainlist' and config.get_setting('downloadenabled') and not item.disable_videolibrary: # Download movie if item.contentType == "movie": context_commands.append((config.get_localized_string(60354), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action))) @@ -715,6 +718,8 @@ def set_context_commands(item, item_url, parent_item, **kwargs): if (item.contentTitle and item.contentType in ['movie', 'tvshow']) or "buscar_trailer" in context: context_commands.append((config.get_localized_string(60359), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({ 'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.contentTitle if item.contentTitle else item.fulltitle, 'contextual': True})))) + if item.nextPage: + context_commands.append((config.get_localized_string(70511), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=gotopage&real_action='+item.action))) if config.dev_mode(): context_commands.insert(0, ("item info", "Container.Update (%s?%s)" % (sys.argv[0], Item(action="itemInfo", parent=item.tojson()).tourl()))) return context_commands @@ -1041,7 +1046,7 @@ def play_video(item, strm=False, force_direct=False, autoplay=False): xlistitem.setProperty("inputstream.adaptive.license_type", item.drm) xlistitem.setProperty("inputstream.adaptive.license_key", item.license) xlistitem.setMimeType('application/dash+xml') - elif item.manifest == 'hls' or mediaurl.split('|')[0].endswith('m3u8'): + elif item.manifest == 'hls' or (mediaurl.split('|')[0].endswith('m3u8') and mediaurl.startswith('http')): if not install_inputstream(): return xlistitem.setProperty('inputstream' if PY3 else 'inputstreamaddon', 'inputstream.adaptive') @@ -1122,23 +1127,23 @@ def get_seleccion(default_action, opciones, seleccion, video_urls): def calcResolution(option): - match = scrapertools.find_single_match(option, '([0-9]{2,4})x([0-9]{2,4})') - resolution = False + match = scrapertools.find_single_match(option, '([0-9]{2,4})(?:p|i|x[0-9]{2,4}|)') + resolution = 0 + if match: - resolution = int(match[0]) * int(match[1]) - else: - if '240p' in option: - resolution = 320 * 240 - elif '360p' in option: - resolution = 480 * 360 - elif ('480p' in option) or ('480i' in option): - resolution = 720 * 480 - elif ('576p' in option) or ('576p' in option): - resolution = 720 * 576 - elif ('720p' in option) or ('HD' in option): - resolution = 1280 * 720 - elif ('1080p' in option) or ('1080i' in option) or ('Full HD' in option): - resolution = 1920 * 1080 + resolution = int(match) + elif 'sd' in option.lower(): + resolution = 480 + elif 'hd' in option.lower(): + resolution = 720 + if 'full' in option.lower(): + resolution = 1080 + elif '2k' in option.lower(): + resolution = 1440 + elif '4k' in option.lower(): + resolution = 2160 + elif 'auto' in option.lower(): + resolution = 10000 return resolution diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index d4a90150..0e909ecc 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -4857,7 +4857,7 @@ msgid "Manual Search" msgstr "" msgctxt "#70511" -msgid "" +msgid "Goto page" msgstr "" msgctxt "#70512" @@ -5772,7 +5772,7 @@ msgid "Open in browser" msgstr "" msgctxt "#70740" -msgid "Your system does not have a web browser, so here's the short link you can open in another device:\n%s" +msgid "Your system does not have a web browser, so here's the link you can open in another device:\n%s" msgstr "" msgctxt "#70741" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index ec4a611f..b515bb2c 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -4856,8 +4856,8 @@ msgid "Manual Search" msgstr "Ricerca Manuale" msgctxt "#70511" -msgid "" -msgstr "" +msgid "Goto page" +msgstr "Vai a pagina" msgctxt "#70512" msgid "Searching in Mymovies" @@ -5772,8 +5772,8 @@ msgid "Open in browser" msgstr "Apri nel browser" msgctxt "#70740" -msgid "Your system does not have a web browser, so here's the short link you can open in another device:\n%s" -msgstr "Il tuo sistema non ha un browser, quindi ecco un link corto che puoi aprire in un altro dispositivo\n%s" +msgid "Your system does not have a web browser, so here's the link you can open in another device:\n%s" +msgstr "Il tuo sistema non ha un browser, quindi ecco il link che puoi aprire in un altro dispositivo:\n%s" msgctxt "#70741" msgid "Search %s" diff --git a/resources/skins/Default/720p/ShortCutMenu.xml b/resources/skins/Default/720p/ShortCutMenu.xml index c7b53108..5df800e4 100644 --- a/resources/skins/Default/720p/ShortCutMenu.xml +++ b/resources/skins/Default/720p/ShortCutMenu.xml @@ -6,14 +6,31 @@ <top>0</top> </coordinates> <controls> + <control type='label' id='200'> + <description>Background Color</description> + <visible>False</visible> + </control> + <control type='label' id='201'> + <description>Overlay Color</description> + <visible>False</visible> + </control> + <control type='label' id='202'> + <description>Selection Color</description> + <visible>False</visible> + </control> + <control type='label' id='203'> + <description>Text Color</description> + <visible>False</visible> + </control> + <control type="button"> <description>Close Button</description> <left>0</left> <top>0</top> <width>100%</width> <height>100%</height> - <texturefocus colordiffuse="77232323">white.png</texturefocus> - <texturenofocus colordiffuse="77232323">white.png</texturenofocus> + <texturefocus colordiffuse="Control.GetLabel(201)">white.png</texturefocus> + <texturenofocus colordiffuse="Control.GetLabel(201)">white.png</texturenofocus> <animation effect="fade" time="200">WindowOpen</animation> <animation effect="fade" time="200">WindowClose</animation> <onclick>Action(close)</onclick> @@ -44,7 +61,7 @@ <left>0</left> <width>100%</width> <height>100%</height> - <texture colordiffuse="Container(1).ListItem.Property(background)">white.png</texture> + <texture colordiffuse="Control.GetLabel(200)">white.png</texture> </control> <control type="grouplist"> @@ -52,7 +69,7 @@ <top>0</top> <left>0</left> <width>100%</width> - <height>220</height> + <height>100%</height> <orientation>vertical</orientation> <control type="list" id="1"> @@ -68,6 +85,7 @@ <pagecontrol>61</pagecontrol> <itemlayout height="220" width="220"> <control type="image"> + <description>Icon</description> <width>220</width> <height>220</height> <texture>$INFO[ListItem.Property(thumbnail)]</texture> @@ -77,12 +95,15 @@ </itemlayout> <focusedlayout height="220" width="220"> <control type="image"> - <top>1</top> - <width>220</width> - <height>218</height> - <texture colordiffuse="Container(1).ListItem.Property(select)">white.png</texture> + <description>Selection</description> + <top>0</top> + <left>0</left> + <width>100%</width> + <height>100%</height> + <texture colordiffuse="Control.GetLabel(202)">white.png</texture> </control> <control type="image"> + <description>Icon</description> <width>220</width> <height>220</height> <texture>$INFO[ListItem.Property(thumbnail)]</texture> @@ -90,13 +111,13 @@ <align>center</align> </control> <control type="textbox"> - <description>Selected Item</description> + <description>Item Title</description> <left>0</left> <top>180</top> <width>100%</width> <height>40</height> <font>font13</font> - <textcolor>FFFFFFFF</textcolor> + <textcolor>Control.GetLabel(203)</textcolor> <label>$INFO[ListItem.Label]</label> <align>center</align> <aligny>center</aligny> @@ -117,6 +138,7 @@ <pagecontrol>61</pagecontrol> <itemlayout height="220" width="220"> <control type="image"> + <description>Icon</description> <width>220</width> <height>220</height> <texture>$INFO[ListItem.Property(thumbnail)]</texture> @@ -126,12 +148,15 @@ </itemlayout> <focusedlayout height="220" width="220"> <control type="image"> - <top>1</top> - <width>220</width> - <height>218</height> - <texture colordiffuse="Container(1).ListItem.Property(select)">white.png</texture> + <description>Selection</description> + <top>0</top> + <left>0</left> + <width>100%</width> + <height>100%</height> + <texture colordiffuse="Control.GetLabel(202)">white.png</texture> </control> <control type="image"> + <description>Icon</description> <width>220</width> <height>220</height> <texture>$INFO[ListItem.Property(thumbnail)]</texture> @@ -139,13 +164,13 @@ <align>center</align> </control> <control type="textbox"> - <description>Selected Item</description> + <description>Item Title</description> <left>0</left> <top>180</top> <width>100%</width> <height>40</height> <font>font13</font> - <textcolor>FFFFFFFF</textcolor> + <textcolor>Control.GetLabel(203)</textcolor> <label>$INFO[ListItem.Label]</label> <align>center</align> <aligny>center</aligny> @@ -155,38 +180,28 @@ </control> <control type="button" id='101'> + <description>Row Down</description> <visible>!String.IsEmpty(Container(1).ListItem.Property(sub)) + !Control.HasFocus(2) + !Control.HasFocus(102)</visible> <animation effect="fade" start="0" end="100" time="200" reversible="true" condition="Control.IsVisible(101)">Conditional</animation> - <!-- <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,0)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,1)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,2)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,3)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,4)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(1).Position,5)">Conditional</animation> --> - <left>520</left> - <top>240</top> - <width>60</width> - <height>60</height> - <texturefocus colordiffuse="Container(1).ListItem.Property(text)">down.png</texturefocus> - <texturenofocus colordiffuse="Container(1).ListItem.Property(text)">down.png</texturenofocus> + <left>540</left> + <top>260</top> + <width>20</width> + <height>20</height> + <texturefocus colordiffuse="Control.GetLabel(203)">dd.png</texturefocus> + <texturenofocus colordiffuse="Control.GetLabel(203)">dd.png</texturenofocus> <aspectratio>keep</aspectratio> </control> <control type="button" id='102'> + <description>Row Up</description> <visible>!Control.HasFocus(1) + !Control.HasFocus(101)</visible> <animation effect="fade" start="0" end="100" time="200" reversible="true" condition="Control.IsVisible(102)">Conditional</animation> - <!-- <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,0)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,1)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,2)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,3)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,4)">Conditional</animation> - <animation effect="slide" end="220,0" condition="Integer.IsGreater(Container(2).Position,5)">Conditional</animation> --> - <left>520</left> + <left>540</left> <top>-80</top> - <width>60</width> - <height>60</height> - <texturefocus colordiffuse="Container(1).ListItem.Property(text)">up.png</texturefocus> - <texturenofocus colordiffuse="Container(1).ListItem.Property(text)">up.png</texturenofocus> + <width>20</width> + <height>20</height> + <texturefocus colordiffuse="Control.GetLabel(203)">uu.png</texturefocus> + <texturenofocus colordiffuse="Control.GetLabel(203)">uu.png</texturenofocus> <aspectratio>keep</aspectratio> </control> </control> <!-- GROUP CONTROLS END --> diff --git a/resources/skins/Default/media/dd.png b/resources/skins/Default/media/dd.png new file mode 100644 index 00000000..8fff3288 Binary files /dev/null and b/resources/skins/Default/media/dd.png differ diff --git a/resources/skins/Default/media/uu.png b/resources/skins/Default/media/uu.png new file mode 100644 index 00000000..14ba6b1d Binary files /dev/null and b/resources/skins/Default/media/uu.png differ diff --git a/servers/ninjastream.py b/servers/ninjastream.py index 53ff6700..426002d7 100644 --- a/servers/ninjastream.py +++ b/servers/ninjastream.py @@ -34,7 +34,7 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= # support.dbg() url = data.get('result',{}).get('playlist') - video_urls.append([url.split('.')[-1], url + '|Referer:' + page_url]) + video_urls.append([url.split('.')[-1], url + '|Referer=' + page_url]) return video_urls diff --git a/servers/playtube.py b/servers/playtube.py index c9df8e0f..a42f2156 100644 --- a/servers/playtube.py +++ b/servers/playtube.py @@ -2,12 +2,10 @@ # -------------------------------------------------------- # Conector playtube By Alfa development Group # -------------------------------------------------------- -import re -import codecs from core import httptools from core import scrapertools from lib import jsunpack -from platformcode import logger +from platformcode import logger, config def test_video_exists(page_url): @@ -24,6 +22,6 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= video_urls = [] pack = scrapertools.find_single_match(data.data, 'p,a,c,k,e,d.*?</script>') unpacked = jsunpack.unpack(pack) - url = scrapertools.find_single_match(unpacked, 'file:"([^"]+)') + "|referer=%s" %(page_url) + url = scrapertools.find_single_match(unpacked, 'file:"([^"]+)') + "|Referer=%s" % page_url video_urls.append(['m3u8 [PlayTube]', url] ) return video_urls \ No newline at end of file diff --git a/servers/vidmoly.py b/servers/vidmoly.py index 14d775a3..29b12330 100644 --- a/servers/vidmoly.py +++ b/servers/vidmoly.py @@ -20,6 +20,6 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= video_urls = support.get_jwplayer_mediaurl(data, 'Vidmoly') for url in video_urls: logger.debug(url) - url[-1] = url[-1].replace(',','').replace('.urlset','').replace('/hls','') + url[-1] = url[-1].replace(',','').replace('.urlset','').replace('/hls','') + '|Referer=' + page_url return video_urls diff --git a/servers/youdbox.py b/servers/youdbox.py index 55e9c17b..e8bd9a74 100644 --- a/servers/youdbox.py +++ b/servers/youdbox.py @@ -11,10 +11,10 @@ def test_video_exists(page_url): data = httptools.downloadpage(page_url).data if 'File was deleted' in data: return False, config.get_localized_string(70449) % 'YouDbox' - return True + return True, "" -def get_video_url(page_url, video_password): +def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("(page_url='%s')" % page_url) global data video_urls = [] @@ -26,4 +26,4 @@ def get_video_url(page_url, video_password): url += decoded.decode("utf8") url = scrapertools.find_single_match(url, '<source src="([^"]+)"') video_urls.append(["[youdbox]", url]) - return video_urls \ No newline at end of file + return video_urls diff --git a/service.py b/service.py index 348adfed..4445e30e 100644 --- a/service.py +++ b/service.py @@ -25,6 +25,11 @@ from platformcode import logger, platformtools, updater, xbmc_videolibrary from specials import videolibrary from servers import torrent +# if this service need to be reloaded because an update changed it +needsReload = False +# list of threads +threads = [] + def check_for_update(): if config.get_setting("update", "videolibrary"): @@ -32,12 +37,9 @@ def check_for_update(): def updaterCheck(): + global needsReload # updater check updated, needsReload = updater.check(background=True) - if needsReload: - xbmc.executescript(__file__) - db.close() - exit(0) def get_ua_list(): @@ -64,6 +66,12 @@ def get_ua_list(): def run_threaded(job_func, args): job_thread = threading.Thread(target=job_func, args=args) job_thread.start() + threads.append(job_thread) + + +def join_threads(): + for th in threads: + th.join() class AddonMonitor(xbmc.Monitor): @@ -77,14 +85,15 @@ class AddonMonitor(xbmc.Monitor): self.scheduleUpdater() self.scheduleUA() - # videolibrary wait - update_wait = [0, 10000, 20000, 30000, 60000] - wait = update_wait[int(config.get_setting("update_wait", "videolibrary"))] - if wait > 0: - xbmc.sleep(wait) - if not config.get_setting("update", "videolibrary") == 2: - check_for_update() - self.scheduleVideolibrary() + if not needsReload: # do not run videolibrary update if service needs to be reloaded + # videolibrary wait + update_wait = [0, 10000, 20000, 30000, 60000] + wait = update_wait[int(config.get_setting("update_wait", "videolibrary"))] + if wait > 0: + xbmc.sleep(wait) + if not config.get_setting("update", "videolibrary") == 2: + run_threaded(check_for_update, (False,)) + self.scheduleVideolibrary() super(AddonMonitor, self).__init__() def onSettingsChanged(self): @@ -201,65 +210,7 @@ if __name__ == "__main__": '/" and strScraper<>"metadata.local"') if nun_records: videolibrarytools.convert_videolibrary() - # dialog = platformtools.dialog_progress(config.get_localized_string(20000), 'Conversione videoteca in corso') - # path_to_delete = [] - # film_lst = glob.glob(xbmc.translatePath( - # filetools.join(config.get_setting('videolibrarypath'), config.get_setting('folder_movies'), - # '*/*.json'))) - # tvshow_lst = glob.glob(xbmc.translatePath( - # filetools.join(config.get_setting('videolibrarypath'), config.get_setting('folder_tvshows'), - # '*/tvshow.nfo'))) - # total = len(film_lst) + len(tvshow_lst) - # progress = 0 - # # set local info only - # xbmc_videolibrary.execute_sql_kodi( - # 'update path set strScraper="metadata.local", strSettings="" where strPath = "' + - # filetools.join(config.get_setting('videolibrarypath'), config.get_setting('folder_tvshows')) + '/"') - # xbmc_videolibrary.execute_sql_kodi( - # 'update path set strScraper="metadata.local", strSettings="" where strPath = "' + - # filetools.join(config.get_setting('videolibrarypath'), config.get_setting('folder_movies')) + '/"') - - # for film in film_lst: - # path_to_delete.append(filetools.dirname(film)) - # it = Item().fromjson(filetools.read(film)) - # it.infoLabels = {'tmdb_id': it.infoLabels['tmdb_id'], 'mediatype':'movie'} - # tmdb.find_and_set_infoLabels(it) - # videolibrarytools.save_movie(it) - # progress += 1 - # dialog.update(int(progress / total * 100)) - # for tvshow in tvshow_lst: - # if not dialog: - # dialog = platformtools.dialog_progress(config.get_localized_string(20000), 'Conversione videoteca in corso') - # js = jsontools.load('\n'.join(filetools.read(tvshow).splitlines()[1:])) - # channels_dict = js.get('library_urls') - # if channels_dict: - # for ch, url in channels_dict.items(): - # dir = filetools.listdir(xbmc.translatePath(filetools.join(config.get_setting('videolibrarypath'), config.get_setting('folder_tvshows'), js['path']))) - # json_files = [f for f in dir if f.endswith('.json')] - # if json_files: - # path_to_delete.append(filetools.dirname(tvshow)) - # nfo, it = videolibrarytools.read_nfo(tvshow) - # it.infoLabels = {'tmdb_id': it.infoLabels['tmdb_id'], 'mediatype':'tvshow'} - # it.contentType = 'tvshow' - # it.channel = ch - # it.url = channels_dict[ch] - # tmdb.find_and_set_infoLabels(it) - # try: - # channel = __import__('channels.%s' % ch, fromlist=['channels.%s' % ch]) - # except: - # channel = __import__('specials.%s' % ch, fromlist=['specials.%s' % ch]) - # it.host = channel.host - # episodes = getattr(channel, 'episodios')(it) - # for ep in episodes: - # logger.debug('EPISODE URL',ep.url) - - # videolibrarytools.save_tvshow(it, episodes, True) - # progress += 1 - # dialog.update(int(progress / total * 100)) - # for path in path_to_delete: - # filetools.rmdirtree(path, True) - # dialog.close() if config.get_setting('autostart'): xbmc.executebuiltin('RunAddon(plugin.video.' + config.PLUGIN_NAME + ')') @@ -283,7 +234,19 @@ if __name__ == "__main__": except: logger.error(traceback.format_exc()) + if needsReload: + join_threads() + db.close() + logger.info('Relaunching service.py') + xbmc.executeJSONRPC( + '{"jsonrpc": "2.0", "id":1, "method": "Addons.SetAddonEnabled", "params": { "addonid": "plugin.video.kod", "enabled": false }}') + xbmc.executeJSONRPC( + '{"jsonrpc": "2.0", "id":1, "method": "Addons.SetAddonEnabled", "params": { "addonid": "plugin.video.kod", "enabled": true }}') + logger.debug(threading.enumerate()) + break + if monitor.waitForAbort(1): # every second + join_threads() # db need to be closed when not used, it will cause freezes db.close() break diff --git a/specials/community.py b/specials/community.py index 1bfb7ae9..a7827ba5 100644 --- a/specials/community.py +++ b/specials/community.py @@ -2,24 +2,29 @@ # -*- Channel Community -*- -import re, inspect, xbmcgui +import re, inspect, mimetypes, xbmcgui from core import httptools, jsontools, tmdb, support, filetools from core.item import Item +from lib import unshortenit from platformcode import config, platformtools, logger from collections import OrderedDict +from core import servertools -info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json -try: lang = info_language[config.get_setting("info_language", "videolibrary")] -except: lang = 'it' +info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json +try: + lang = info_language[config.get_setting("info_language", "videolibrary")] +except: + lang = 'it' defpage = ["", "20", "40", "60", "80", "100"] -defp = defpage[config.get_setting('pagination','community')] +defp = defpage[config.get_setting('pagination', 'community')] disable_pagination = False -show_seasons = config.get_setting('show_seasons','community') +show_seasons = config.get_setting('show_seasons', 'community') tmdb_api = 'a1ab8b8669da03637a4b98fa39c39228' + def mainlist(item): logger.debug() @@ -37,19 +42,19 @@ def show_channels(item): itemlist = [] # add context menu - context = [{"title": config.get_localized_string(50005), "action": "remove_channel", "channel": "community"}] + context = [{"title": config.get_localized_string(50005), "action": "remove_channel", "channel": "community"}] # read json json = load_and_check(item) itemlist.append(Item(channel=item.channel, - title=support.typo(config.get_localized_string(70676),'bold color kod'), + title=support.typo(config.get_localized_string(70676), 'bold color kod'), action='add_channel', thumbnail=support.thumb('add'))) for key, channel in json['channels'].items(): - path = filetools.dirname(channel['path']) # relative path - channel_json = load_json(channel) # read channel json + path = filetools.dirname(channel['path']) # relative path + channel_json = load_json(channel) # read channel json # retrieve information from json thumbnail = relative('thumbnail', channel_json, path) @@ -58,13 +63,13 @@ def show_channels(item): plot = channel_json['plot'] if 'plot' in channel_json else '' itemlist.append(Item(channel=item.channel, - title=support.typo(channel['channel_name'],'bold'), + title=support.typo(channel['channel_name'], 'bold'), url=channel['url'] if 'url' in channel else path, thumbnail=thumbnail, fanart=fanart, plot=plot, action='show_menu', - channel_id = key, + channel_id=key, context=context, path=path)) @@ -76,8 +81,7 @@ def show_menu(item): logger.debug() itemlist = [] - - if item.menu: # if second level menu + if item.menu: # if second level menu get_sub_menu(item, item.menu, 'level2', itemlist) else: if type(item.url) == dict: @@ -102,14 +106,12 @@ def show_menu(item): itemlist += get_seasons(item) elif key in ['episodes_list']: itemlist += episodios(item, json, key) - elif key in ['links']: + elif key in ['links', 'find_links']: itemlist += findvideos(item) elif key in ['search'] and 'url' in json['search']: search_json = json['search'] itemlist += get_search_menu(item, search_json) - - if 'channel_name' in json and not 'disable_search' in json and 'search' not in json: itemlist += get_search_menu(item, json, channel_name=json['channel_name']) logger.debug('PAGINATION:', disable_pagination) @@ -117,7 +119,7 @@ def show_menu(item): def search(item, text): - logger.info('search',text) + logger.info('search', text) itemlist = [] if item.custom_search: @@ -141,6 +143,7 @@ def search(item, text): return itemlist + def global_search(item, text): itemlist = [] json = load_json(item) @@ -148,7 +151,8 @@ def global_search(item, text): if 'menu' in json: for option in json['menu']: - if option in ['submenu', 'level2'] and 'seach' in json['menu'][option] and 'url' in json['menu'][option]['search']: + if option in ['submenu', 'level2'] and 'seach' in json['menu'][option] and 'url' in json['menu'][option][ + 'search']: item.custom_search = json['menu'][option]['search']['url'] itemlist += search(item, text) else: @@ -157,15 +161,13 @@ def global_search(item, text): if item.url: itemlist += global_search(item, text) - if any(key in json for key in ['movies_list','tvshows_list', 'generic_list']): + if any(key in json for key in ['movies_list', 'tvshows_list', 'generic_list']): itemlist += search(item, text) return itemlist - - def peliculas(item, json='', key='', itemlist=[]): - item.plot = item.thumb = item.fanart ='' + item.plot = item.thumb = item.fanart = '' logger.debug('PAGINATION:', item.disable_pagination) if not json: key = item.key @@ -173,25 +175,28 @@ def peliculas(item, json='', key='', itemlist=[]): else: json = json[key] + # logger.debug('DEBUG:', json) + infoLabels = item.infoLabels if item.infoLabels else {} contentType = 'tvshow' if 'tvshow' in key else 'movie' itlist = filterkey = [] action = 'findvideos' - if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'search'] and not item.filterkey and not item.disable_pagination: + if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', + 'search'] and not item.filterkey and not item.disable_pagination: Pagination = int(defp) if defp.isdigit() else '' - else: Pagination = '' + else: + Pagination = '' pag = item.page if item.page else 1 for i, option in enumerate(json): if Pagination and (pag - 1) * Pagination > i: continue # pagination if Pagination and i >= pag * Pagination: break if item.filterkey and item.filterkey in option: - filterkey = [it.lower() for it in option[item.filterkey]] if type(option[item.filterkey]) == list else [option[item.filterkey].lower()] + filterkey = [it.lower() for it in option[item.filterkey]] if type(option[item.filterkey]) == list else [ + option[item.filterkey].lower()] else: filterkey = [] - - title = option['title'] if 'title' in option else '' if 'tvshows_list' in key and 'links' not in option: @@ -199,26 +204,32 @@ def peliculas(item, json='', key='', itemlist=[]): # filter elements if (not item.filter or item.filter.lower() in filterkey) and item.search.lower() in title.lower() and title: + + if 'generic_list' in key and 'links' not in option and 'url' in option: + option['links'] = [] + option['links'].append({'url': option['url']}) + option['url'] = '' + extra = set_extra_values(item, option, item.path) infoLabels['year'] = option['year'] if 'year' in option else '' infoLabels['tmdb_id'] = option['tmdb_id'] if 'tmdb_id' in option else '' - it = Item(channel = item.channel, - title = set_title(title, extra.language, extra.quality), - fulltitle = title, - show = title, - contentTitle = title if contentType == 'movie' else '', - contentSerieName = title if contentType != 'movie' else '', - contentType = contentType, - infoLabels = infoLabels, - url = extra.url, - path = item.path, - thumbnail = extra.thumb, - fanart = extra.fanart, - plot = extra.plot, - personal_plot = extra.plot, - action = action) + it = Item(channel=item.channel, + title=set_title(title, extra.language, extra.quality), + fulltitle=title, + show=title, + contentTitle=title if contentType == 'movie' else '', + contentSerieName=title if contentType != 'movie' else '', + contentType=contentType, + infoLabels=infoLabels, + url=extra.url, + path=item.path, + thumbnail=extra.thumb, + fanart=extra.fanart, + plot=extra.plot, + personal_plot=extra.plot, + action=action) itlist.append(it) if not 'generic_list' in key: @@ -241,8 +252,10 @@ def get_seasons(item): itemlist = [] infoLabels = item.infoLabels json = item.url if type(item.url) == dict else item.url - if 'seasons_list' in json: json = json['seasons_list'] - elif 'tvshows_list' in json: return show_menu(item) + if 'seasons_list' in json: + json = json['seasons_list'] + elif 'tvshows_list' in json: + return show_menu(item) for option in json: infoLabels['season'] = option['season'] title = config.get_localized_string(60027) % option['season'] @@ -262,12 +275,14 @@ def get_seasons(item): contentType='season' if show_seasons else 'tvshow', path=extra.path)) - if inspect.stack()[2][3] in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'get_newest'] or show_seasons == False: + if inspect.stack()[2][3] in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', + 'get_newest'] or show_seasons == False: itlist = [] for item in itemlist: itlist = episodios(item) itemlist = itlist - if inspect.stack()[2][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'get_newest'] and defp and not item.disable_pagination: + if inspect.stack()[2][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', + 'get_newest'] and defp and not item.disable_pagination: itemlist = pagination(item, itemlist) if show_seasons: @@ -276,10 +291,10 @@ def get_seasons(item): return itemlist -def episodios(item, json ='', key='', itemlist =[]): +def episodios(item, json='', key='', itemlist=[]): logger.debug() infoLabels = item.infoLabels - itm=item + itm = item if type(item.url) == dict: if 'seasons_list' in item.url: @@ -303,9 +318,11 @@ def episodios(item, json ='', key='', itemlist =[]): ep = 1 season = infoLabels['season'] if 'season' in infoLabels else item.contentSeason if item.contentSeason else 1 - if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'search'] and not show_seasons: + if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', + 'search'] and not show_seasons: Pagination = int(defp) if defp.isdigit() else '' - else: Pagination = '' + else: + Pagination = '' pag = item.page if item.page else 1 # make items @@ -314,7 +331,7 @@ def episodios(item, json ='', key='', itemlist =[]): if Pagination and i >= pag * Pagination: break # build numeration of episodes numeration = option['number'] if 'number' in option else option['title'] - match = support.match(numeration , patron=r'(?P<season>\d+)x(?P<episode>\d+)').match + match = support.match(numeration, patron=r'(?P<season>\d+)x(?P<episode>\d+)').match if match: episode_number = match[1] ep = int(match[1]) + 1 @@ -337,25 +354,25 @@ def episodios(item, json ='', key='', itemlist =[]): title = '%sx%s%s' % (season_number, episode_number, title) extra = set_extra_values(item, option, item.path) if not item.filterseason or season_number == int(item.filterseason): - itemlist.append(Item(channel = item.channel, - title = set_title(title, extra.language, extra.quality), - fulltitle = item.fulltitle, - show = item.show, - url = option, - action = 'findvideos', - plot = extra.plot, - thumbnail= extra.thumb if extra.thumb else item.thumbnail, - fanart = extra.fanart, - contentSeason = season_number, - contentEpisode = episode_number, - infoLabels = infoLabels, - contentType = 'episode', - path = item.path)) + itemlist.append(Item(channel=item.channel, + title=set_title(title, extra.language, extra.quality), + fulltitle=item.fulltitle, + show=item.show, + url=option, + action='findvideos', + plot=extra.plot, + thumbnail=extra.thumb if extra.thumb else item.thumbnail, + fanart=extra.fanart, + contentSeason=season_number, + contentEpisode=episode_number, + infoLabels=infoLabels, + contentType='episode', + path=item.path)) # if showseason if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'get_newest', 'search']: if show_seasons and not item.filterseason: - itm.contentType='season' + itm.contentType = 'season' season_list = [] for item in itemlist: if item.contentSeason not in season_list: @@ -370,7 +387,7 @@ def episodios(item, json ='', key='', itemlist =[]): url=itm.url, action='episodios', contentSeason=season, - contentType = 'episode', + contentType='episode', infoLabels=infoLabels, filterseason=str(season), path=item.path)) @@ -390,17 +407,46 @@ def episodios(item, json ='', key='', itemlist =[]): # Find Servers def findvideos(item): - logger.debug() + # logger.debug('DEBUG', item) item.contentTitle = item.fulltitle itemlist = [] + json = [] if 'links' in item.url: json = item.url['links'] + elif 'find_links' in item.url: + for link in item.url['find_links']: + link['url'] = unshortenit.findlinks(link['url']) + mimetype = findS = None + mimetype = mimetypes.MimeTypes().guess_type(link['url'])[0] + if mimetype is None: + findS = servertools.get_server_from_url(link['url']) + if mimetype is None and findS is None: + data = support.match(link['url']).data + itemlist_url = servertools.find_video_items(data=data) + if len(itemlist_url): + for item_url in itemlist_url: + valid = True + patterns = link.get('patterns', False) + if patterns: + valid = False + for pattern in patterns: + match = re.search(pattern, item_url.url) + if match: + valid = True + break + if valid: + json.append({"url": item_url.url}) + else: + json.append(link) + else: - json = item.url + url = item.url + item.url = {} + json.append({"url": url}) + # support.dbg() for option in json: extra = set_extra_values(item, option, item.path) - itemlist.append( item.clone(url=option['url'], action='play', @@ -408,32 +454,34 @@ def findvideos(item): contentLanguage=extra.language, extraInfo=extra.info)) + videolibrary = item.url.get('videolibrary', True) + item.autoplay = item.url.get('autoplay', False) + item.url = '' # do not pass referer - return support.server(item, itemlist=itemlist) + return support.server(item, itemlist=itemlist, Videolibrary=videolibrary) ################################ Menu ################################ def get_menu(item, json, key, itemlist=[]): - logger.debug() json = json[key] for option in json: title = option['title'] if 'title' in option else json[option] if 'search' not in option else '' extra = set_extra_values(item, option, item.path) - level2 = option if 'level2' in option else [] - it = Item(channel = item.channel, - title = support.typo(title, 'bullet bold'), - fulltitle = title, - show = title, - url = extra.url, - path = item.path, - thumbnail = extra.thumb, - fanart = extra.fanart, - plot = extra.plot, - action = 'show_menu', - menu = level2 if not item.menu else None, - filterkey = extra.filterkey, - filter = extra.filter) + level2 = option if 'level2' in option else [] + it = Item(channel=item.channel, + title=support.typo(title, 'bullet bold'), + fulltitle=title, + show=title, + url=extra.url, + path=item.path, + thumbnail=extra.thumb, + fanart=extra.fanart, + plot=extra.plot, + action='show_menu', + menu=level2 if not item.menu else None, + filterkey=extra.filterkey, + filter=extra.filter) if title: itemlist.append(it) @@ -441,7 +489,7 @@ def get_menu(item, json, key, itemlist=[]): get_search_menu(it, json, itemlist) elif 'submenu' in option: - get_sub_menu(it, option, 'submenu' ,itemlist) + get_sub_menu(it, option, 'submenu', itemlist) for item in itemlist: if not item.thumbnail: support.thumb(item) @@ -462,20 +510,20 @@ def get_sub_menu(item, json, key, itemlist=[]): extra = set_extra_values(item, json[option], item.path) if not extra.url: extra.url = item.url filterkey = option - level2 = option if 'level2' in option else [] - it = Item(channel = item.channel, - title = support.typo(title,'submenu'), - fulltitle = title, - show = title, - url = extra.url, - path = item.path, - thumbnail = extra.thumb, - fanart = extra.fanart, - plot = extra.plot, - action = 'show_menu', - menu = level2 if not item.menu else None, - filterkey = filterkey, - description = extra.description) + level2 = option if 'level2' in option else [] + it = Item(channel=item.channel, + title=support.typo(title, 'submenu'), + fulltitle=title, + show=title, + url=extra.url, + path=item.path, + thumbnail=extra.thumb, + fanart=extra.fanart, + plot=extra.plot, + action='show_menu', + menu=level2 if not item.menu else None, + filterkey=filterkey, + description=extra.description) itemlist.append(it) if 'search' in option: @@ -499,7 +547,7 @@ def get_search_menu(item, json='', itemlist=[], channel_name=''): extra = set_extra_values(item, json, item.path) itemlist.append(Item(channel=item.channel, - title=support.typo(title,'submenu bold'), + title=support.typo(title, 'submenu bold'), fulltitle=title, show=title, thumbnail=extra.thumb, @@ -514,7 +562,7 @@ def get_search_menu(item, json='', itemlist=[], channel_name=''): return itemlist -def submenu(item, json, key, itemlist = [], filter_list = []): +def submenu(item, json, key, itemlist=[], filter_list=[]): logger.debug(item) import sys if sys.version_info[0] >= 3: @@ -526,8 +574,10 @@ def submenu(item, json, key, itemlist = [], filter_list = []): if type(item.description) == dict: description = item.description else: - if ':/' in item.description: url = item.description - else: url = filetools.join(item.path, item.description) + if ':/' in item.description: + url = item.description + else: + url = filetools.join(item.path, item.description) description = load_json(url, no_order=True) else: description = None @@ -584,8 +634,11 @@ def filter_thread(filter, key, item, description): results = tmdb_inf.results[0] id = results['id'] if id: - thumbnail = 'https://image.tmdb.org/t/p/original' + results['profile_path'] if results['profile_path'] else item.thumbnail - json_file = httptools.downloadpage('http://api.themoviedb.org/3/person/'+ str(id) + '?api_key=' + tmdb_api + '&language=en', use_requests=True).data + thumbnail = 'https://image.tmdb.org/t/p/original' + results['profile_path'] if results[ + 'profile_path'] else item.thumbnail + json_file = httptools.downloadpage( + 'http://api.themoviedb.org/3/person/' + str(id) + '?api_key=' + tmdb_api + '&language=en', + use_requests=True).data plot += jsontools.load(json_file)['biography'] if description: @@ -595,7 +648,6 @@ def filter_thread(filter, key, item, description): fanart = extra.fanart if extra.fanart else item.fanart plot = extra.plot if extra.plot else item.plot - item = Item(channel=item.channel, title=support.typo(filter, 'bold'), url=item.url, @@ -673,25 +725,27 @@ def set_extra_values(item, json, path): if key == 'quality': ret.quality = json[key] if ret.quality and not ret.quality[0].isdigit(): ret.quality = ret.quality.upper() - elif key == 'language': + elif key == 'language': ret.language = json[key].upper() - elif key == 'plot': + elif key == 'plot': ret.plot = json[key] elif key in ['poster', 'thumbnail']: - ret.thumb = json[key] if ':/' in json[key] else filetools.join(path,json[key]) if '/' in json[key] else support.thumb(json[key]) - elif key == 'fanart': - ret.fanart = json[key] if ':/' in json[key] else filetools.join(path,json[key]) + ret.thumb = json[key] if ':/' in json[key] else filetools.join(path, json[key]) if '/' in json[key] else support.get_thumb(json[key]) + elif key == 'fanart': + ret.fanart = json[key] if ':/' in json[key] else filetools.join(path, json[key]) elif key in ['url', 'link']: - ret.url = json[key] if ':/' in json[key] or type(json[key]) == dict else filetools.join(path,json[key]) - elif key == 'seasons_list': + ret.url = json[key] if ':/' in json[key] or type(json[key]) == dict else filetools.join(path, json[key]) + elif key == 'seasons_list': ret.url = {} ret.url['seasons_list'] = json['seasons_list'] - elif key == 'episodes_list': + elif key == 'episodes_list': ret.url = {} ret.url['episodes_list'] = json['episodes_list'] - elif key == 'links': - ret.url={} - ret.url['links'] = json[key] + elif key in ['links', 'find_links']: + ret.url = {} + ret.url[key] = json[key] + ret.url['videolibrary'] = json.get('videolibrary', True) + ret.url['autoplay'] = json.get('autoplay', False) elif key == 'filter': filterkey = json[key].keys()[0] ret.filter = json[key][filterkey] @@ -711,6 +765,7 @@ def set_extra_values(item, json, path): if not ret.plot: ret.plot = item.plot + logger.debug(ret.url) return ret @@ -720,8 +775,8 @@ def set_title(title, language='', quality='', info=''): t = support.match(title, patron=r'\{([^\}]+)\}').match if 'bold' not in t: t += ' bold' - title = re.sub(r'(\{[^\}]+\})','',title) - title = support.typo(title,t) + title = re.sub(r'(\{[^\}]+\})', '', title) + title = support.typo(title, t) if quality: title += support.typo(quality, '_ [] color kod bold') @@ -743,14 +798,14 @@ def relative(key, json, path): ret = '' if key in json: if key in ['thumbnail', 'poster']: - ret = json[key] if ':/' in json[key] else filetools.join(path,json[key]) if '/' in json[key] else support.thumb(json[key]) if json[key] else '' + ret = json[key] if ':/' in json[key] else filetools.join(path, json[key]) if '/' in json[key] else support.get_thumb(json[key]) if json[key] else '' else: - ret = json[key] if ':/' in json[key] else filetools.join(path,json[key]) if '/' in json[key] else '' + ret = json[key] if ':/' in json[key] else filetools.join(path, json[key]) if '/' in json[key] else '' return ret -def pagination(item, itemlist = []): +def pagination(item, itemlist=[]): logger.debug() itlist = [] @@ -763,12 +818,13 @@ def pagination(item, itemlist = []): encoded_itemlist.append(it.tourl()) if inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes', 'search']: Pagination = int(defp) if defp.isdigit() else '' - else: Pagination = '' + else: + Pagination = '' pag = item.page if item.page else 1 for i, item in enumerate(itemlist): if Pagination and (pag - 1) * Pagination > i: continue # pagination - if Pagination and i >= pag * Pagination: break # pagination + if Pagination and i >= pag * Pagination: break # pagination itlist.append(item) @@ -776,28 +832,30 @@ def pagination(item, itemlist = []): if inspect.stack()[1][3] != 'get_newest': itlist.append( Item(channel=item.channel, - action = 'pagination', - contentType=item.contentType, - title=support.typo(config.get_localized_string(30992), 'color kod bold'), - fulltitle= item.fulltitle, - show= item.show, - url=item.url, - args=item.args, - page=pag + 1, - path=item.path, - media_type=item.media_type, - thumbnail=support.thumb(), - itemlist= encoded_itemlist)) + action='pagination', + contentType=item.contentType, + title=support.typo(config.get_localized_string(30992), 'color kod bold'), + fulltitle=item.fulltitle, + show=item.show, + url=item.url, + args=item.args, + page=pag + 1, + path=item.path, + media_type=item.media_type, + thumbnail=support.thumb(), + itemlist=encoded_itemlist)) return itlist + def add_channel(item): logger.debug() channel_to_add = {} json_file = '' - result = platformtools.dialog_select(config.get_localized_string(70676), [config.get_localized_string(70678), config.get_localized_string(70679)]) + result = platformtools.dialog_select(config.get_localized_string(70676), + [config.get_localized_string(70678), config.get_localized_string(70679)]) if result == -1: return - if result==0: + if result == 0: file_path = xbmcgui.Dialog().browseSingle(1, config.get_localized_string(70680), 'files') try: channel_to_add['path'] = file_path @@ -807,7 +865,7 @@ def add_channel(item): except: pass - elif result==1: + elif result == 1: url = platformtools.dialog_input("", config.get_localized_string(70681), False) try: if url[:4] != 'http': @@ -831,19 +889,21 @@ def add_channel(item): community_json = jsontools.load(community_json.read()) id = 1 while str(id) in community_json['channels']: - id +=1 - community_json['channels'][str(id)]=(channel_to_add) + id += 1 + community_json['channels'][str(id)] = (channel_to_add) with open(path, "w") as file: - file.write(jsontools.dump(community_json)) + file.write(jsontools.dump(community_json)) file.close() - platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(70683) % json_file['channel_name']) + platformtools.dialog_notification(config.get_localized_string(20000), + config.get_localized_string(70683) % json_file['channel_name']) import xbmc xbmc.sleep(1000) platformtools.itemlist_refresh() return + def remove_channel(item): logger.debug() @@ -856,9 +916,10 @@ def remove_channel(item): to_delete = community_json['channels'][id]['channel_name'] del community_json['channels'][id] with open(path, "w") as file: - file.write(jsontools.dump(community_json)) + file.write(jsontools.dump(community_json)) file.close() - platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(70684) % to_delete) + platformtools.dialog_notification(config.get_localized_string(20000), + config.get_localized_string(70684) % to_delete) platformtools.itemlist_refresh() return diff --git a/specials/filmontv.py b/specials/filmontv.py index 780a7dfb..818d3068 100644 --- a/specials/filmontv.py +++ b/specials/filmontv.py @@ -258,6 +258,7 @@ def live(item): # make itemlist for ch in channel_list: itemlist += channels_dict[ch] + itemlist.sort(key=lambda it: support.channels_order[it.fulltitle]) return itemlist diff --git a/specials/news.py b/specials/news.py index ea83c2c1..8d1e87ee 100644 --- a/specials/news.py +++ b/specials/news.py @@ -395,13 +395,14 @@ def get_title(item): # title = re.compile("\[.*?\]", re.DOTALL).sub("", item.contentSerieName) if not scrapertools.get_season_and_episode(title) and item.contentEpisodeNumber: # contentSeason non c'è in support - if not item.contentSeason: - item.contentSeason = '1' - title = "%sx%s - %s" % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2), title) + if item.contentSeason: + title = '{}x{:02d}. {}'.format(item.contentSeason, item.contentEpisodeNumber, title) + else: + title = '{:02d}. {}'.format(item.contentEpisodeNumber, title) else: seas = scrapertools.get_season_and_episode(item.title) if seas: - title = "%s - %s" % (seas, title) + title = "{}. {}".format(seas, title) elif item.contentTitle: # If it is a movie with the adapted channel title = item.contentTitle diff --git a/specials/search.py b/specials/search.py index 9499a14c..612e38c3 100644 --- a/specials/search.py +++ b/specials/search.py @@ -571,7 +571,7 @@ def genres_menu(item): action='discover_list', discovery=discovery, mode=item.mode)) from core import support - support.thumb(itemlist, genre=True) + support.thumb(itemlist, mode='genre') return sorted(itemlist, key=lambda it: it.title) @@ -724,12 +724,14 @@ def discover_list(item): elif len(result) > 19 and item.discovery: item.discovery['page'] = str(int(item.discovery['page']) + 1) - itemlist.append(Item(channel=item.channel, action='discover_list', title=typo(config.get_localized_string(30992), 'color kod bold'), - list_type=item.list_type, discovery=item.discovery, thumbnail=thumb())) + itemlist.append(Item(channel=item.channel, action='discover_list', nextPage=True, + title=typo(config.get_localized_string(30992), 'color kod bold'), + list_type=item.list_type, discovery=item.discovery, thumbnail=thumb(), page=item.discovery['page'])) elif len(result) > 19: next_page = str(int(item.page) + 1) - itemlist.append(Item(channel=item.channel, action='discover_list', title=typo(config.get_localized_string(30992), 'color kod bold'), + itemlist.append(Item(channel=item.channel, action='discover_list', nextPage=True, + title=typo(config.get_localized_string(30992), 'color kod bold'), list_type=item.list_type, search_type=item.search_type, mode=item.mode, page=next_page, thumbnail=thumb())) return itemlist @@ -791,8 +793,8 @@ def get_from_temp(item): results = [Item().fromurl(elem) for elem in item.itemlist[prevp:nextp]] if nextp < nTotal: - results.append(Item(channel='search', title=typo(config.get_localized_string(30992),'bold color kod'), - action='get_from_temp', itemlist=item.itemlist, page=item.page + 1)) + results.append(Item(channel='search', title=typo(config.get_localized_string(30992), 'bold color kod'), + action='get_from_temp', itemlist=item.itemlist, page=item.page + 1, nextPage=True)) tmdb.set_infoLabels_itemlist(results, True) for elem in results: diff --git a/specials/tvmoviedb.py b/specials/tvmoviedb.py index 0853a331..13c070cc 100644 --- a/specials/tvmoviedb.py +++ b/specials/tvmoviedb.py @@ -1912,7 +1912,7 @@ def acciones_trakt(item): post = None if item.post: post = jsontools.dump(item.post) - url = "http://api-v2launch.trakt.tv/%s" % item.url + url = "http://api.trakt.tv/%s" % item.url data = httptools.downloadpage(url, post=post, headers=headers) if data.code == "401": trakt_tools.token_trakt(item.clone(args="renew")) @@ -2379,7 +2379,7 @@ def indices_mal(item): if not url.startswith('http'): url = "https://myanimelist.net" + url itemlist.append(Item(channel=item.channel, action="season_mal", title=typo(title, 'bold'), url=url, thumbnail=thumbnail, fanart=thumbnail)) - return thumb(itemlist, genre=True) + return thumb(itemlist, mode='genre') def season_mal(item): diff --git a/tests/test_generic.py b/tests/test_generic.py index 111b4329..3b2ebd1f 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -64,7 +64,7 @@ validUrlRegex = re.compile( r'(?::\d+)?' # optional port r'(?:/?|[/?]\S+)$', re.IGNORECASE) -chBlackList = ['url', 'mediasetplay'] +chBlackList = ['url', 'mediasetplay', 'metalvideo'] srvBlacklist = ['mega', 'hdmario', 'torrent', 'youtube'] chNumRis = { 'altadefinizione01': { @@ -76,7 +76,7 @@ chNumRis = { }, 'altadefinizioneclick': { 'Film': 36, - 'Serie TV': 12, + 'Serie TV': 36, }, 'casacinema': { 'Film': 10, @@ -315,7 +315,7 @@ class GenericServerTest(unittest.TestCase): def test_get_video_url(self): module = __import__('servers.%s' % self.name, fromlist=["servers.%s" % self.name]) page_url = self.server.url - httptools.default_headers['Referer'] = self.server.referer + # httptools.default_headers['Referer'] = self.server.referer print('testing ' + page_url) print('Found on ' + self.server.foundOn) print()