diff --git a/addon.xml b/addon.xml index d1bda1d5..f33d85da 100644 --- a/addon.xml +++ b/addon.xml @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ - + video @@ -27,7 +27,10 @@ resources/media/screenshot-2.png resources/media/screenshot-3.png - - fix vari + - Nuove visualizzazioni Server +- Fix Gestione Viste +- Aggiunto Pluto TV +- Fix e migliorie varie 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] @@ -38,6 +41,6 @@ https://t.me/kodiondemand https://github.com/kodiondemand/addon - + \ No newline at end of file diff --git a/channels.json b/channels.json index ff9a5c2d..7474965f 100644 --- a/channels.json +++ b/channels.json @@ -1,10 +1,8 @@ { "direct": { - "altadefinizione01": "https://www.altadefinizione01.day", - "altadefinizione01_link": "https://altadefinizione01.travel", + "altadefinizione01": "https://www.altadefinizione01.sbs", "animealtadefinizione": "https://www.animealtadefinizione.it", "animeforce": "https://www.animeforce.it", - "animeleggendari": "https://animezeus.com", "animesaturn": "https://www.animesaturn.it", "animeunity": "https://www.animeunity.tv", "animeuniverse": "https://www.animeuniverse.it", @@ -12,14 +10,11 @@ "aniplay": "https://aniplay.it", "casacinema": "https://www.casacinema.page", "cb01anime": "https://www.cineblog01.red", - "cineblog01": "https://cb01.uno", "cinemalibero": "https://cinemalibero.top", - "cinetecadibologna": "https://cinestore.cinetecadibologna.it", + "cinetecadibologna": "http://cinestore.cinetecadibologna.it", "discoveryplus": "https://www.discoveryplus.com", - "dreamsub": "https://dreamsub.stream", - "dsda": "https://www.dsda.press", + "dreamsub": "https://dreamsub.cc", "eurostreaming": "https://eurostreaming.town", - "filmigratis": "https://filmigratis.org", "guardaseriecam": "https://guardaserie.cam", "guardaserieclick": "https://www.guardaserie.builders", "guardaserieicu": "https://guardaserie.construction", @@ -33,23 +28,20 @@ "paramount": "https://www.mtv.it", "piratestreaming": "https://www.piratestreaming.design", "plutotv": "https://pluto.tv", - "polpotv": "https://roma.polpo.tv", "raiplay": "https://www.raiplay.it", - "seriehd": "https://altadefinizionecommunity.casa", - "serietvonline": "https://serietvonline.art", - "serietvsubita": "http://serietvsubita.xyz", "serietvu": "https://www.serietvu.live", "streamingcommunity": "https://streamingcommunity.host", "streamingita": "https://www.streamingita.site", "streamtime": "https://t.me/s/StreamTime", "tantifilm": "https://www.tantifilm.codes", - "tapmovie": "https://it.tapmovie.net", "toonitalia": "https://toonitalia.co", "vvvvid": "https://www.vvvvid.it" }, "findhost": { + "altadefinizione": "https://altadefinizione.nuovo.live", "altadefinizionecommunity": "https://altaregistrazione.net", "animealtadefinizione": "https://www.animealtadefinizione.it", + "cineblog01": "https://cb01.uno", "filmpertutti": "https://filmpertuttiii.nuovo.live" } } \ No newline at end of file diff --git a/channels/altadefinizione.json b/channels/altadefinizione.json new file mode 100644 index 00000000..7859ff31 --- /dev/null +++ b/channels/altadefinizione.json @@ -0,0 +1,10 @@ +{ + "id": "altadefinizione", + "name": "Altadefinizione", + "language": ["ita", "sub-ita"], + "active": false, + "thumbnail": "altadefinizione.png", + "banner": "altadefinizione.png", + "categories": ["movie", "tvshow", "vos"], + "settings": [] +} diff --git a/channels/altadefinizione.py b/channels/altadefinizione.py new file mode 100644 index 00000000..133d9db9 --- /dev/null +++ b/channels/altadefinizione.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------ +# Canale per altadefinizione +# ------------------------------------------------------------ + + +from core import httptools, support +from platformcode import config, logger + + +def findhost(url): + host = support.match(url, patron=r']+>(?P[^<]+)' + return locals() + + +def search(item, text): + logger.debug(text) + item.url = "{}/?s={}".format(host, text) + + try: + return peliculas(item) + + except: + import sys + for line in sys.exc_info(): + logger.error("search except: %s" % line) + return [] + + +@support.scrape +def peliculas(item): + n = '22' if '/?s=' in item.url else '8' + item.contentType = "undefined" + action = 'check' + patron = r'data-src="(?P<thumb>http[^"]+)(?:[^>]+>){' + n + r'}\s*<a href="(?P<url>[^"]+)[^>]+>\s*(?P<title>[^\[\(\<]+)(?:\[(?P<quality>[^\]]+)\])?\s*(?:\((?P<lang>[a-zA-z-]+)\))?\s*(?:\((?P<year>\d+)\))?\s*</a>\s*</h2>' + patronNext = r'href="([^"]+)[^>]+>»' + return locals() + + +@support.scrape +def episodios(item): + item.quality = '' + data = item.data + action='findvideos' + patronBlock = r'Stagione[^;]+;\s(?P<lang>(?:Sub-)?ITA)(?: in )?(?P<quality>[^<]*)?(?:[^>]+>){4}(?P<block>.*?)/p>' + patron = r'(?P<season>\d+)&[^:]+;(?P<episode>\d+)(?P<data>.*?)(?:<br|$)' + return locals() + + +def check(item): + item.data = httptools.downloadpage(item.url).data + if 'rel="tag">Serie TV' in item.data: + return episodios(item) + else: + return findvideos(item) + + +def findvideos(item): + logger.debug() + if item.contentType == 'movie': + item.data = support.match(item.data, patron=r'data-id="([^"]+)').matches + return support.server(item, item.data) diff --git a/channels/altadefinizione01_link.json b/channels/altadefinizione01_link.json deleted file mode 100644 index 429fd83c..00000000 --- a/channels/altadefinizione01_link.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "altadefinizione01_link", - "name": "Altadefinizione01 L", - "active": false, - "language": ["ita","sub-ita"], - "thumbnail": "altadefinizione01_L.png", - "banner": "altadefinizione01_L.png", - "categories": ["movie","vos"], - "settings" :[] -} diff --git a/channels/altadefinizione01_link.py b/channels/altadefinizione01_link.py deleted file mode 100644 index e1e28686..00000000 --- a/channels/altadefinizione01_link.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- -# -*- Channel altadefinizione01_link -*- - -from core import support -from core.item import Item -from platformcode import config, logger - -__channel__ = "altadefinizione01_link" - -# ======== def per utility INIZIO ============================ -host = config.get_channel_url() -headers = [['Referer', host]] - - -# =========== home menu =================== -@support.menu -def mainlist(item): - support.info('mainlist',item) - - film = [ - ('Al Cinema', ['/film-del-cinema', 'peliculas', '']), - ('Generi', ['', 'genres', 'genres']), - ('Anni', ['', 'genres', 'years']), - ('Qualità', ['/piu-visti.html', 'genres', 'quality']), - ('Mi sento fortunato', ['/piu-visti.html', 'genres', 'lucky']), - ('Popolari', ['/piu-visti.html', 'peliculas', '']), - ('Sub-ITA', ['/film-sub-ita/', 'peliculas', '']) - ] - return locals() - -# ======== def in ordine di action dal menu =========================== - -@support.scrape -def peliculas(item): - # debug = True - support.info('peliculas',item) - - patron = r'<a href="(?P<url>[^"]+)">(?P<title>[^<]+)(?:[^>]+>){5}\s*<div class="[^"]+" style="background-image:url\((?P<thumb>[^\)]+)(?:[^>]+>){6}\s*(?P<year>\d{4})[^>]+>[^>]+>(?:\s*(?P<duration>\d+))?(?:[^>]+>){0,2}\s+(?P<quality>[a-zA-Z]+)\s+(?:[^>]+>){2}\s*(?P<lang>[^>]+)\s+[^>]+>' - patronNext = r'<span>\d</span> <a href="([^"]+)">' - # debug = True - return locals() - -# =========== def pagina categorie ====================================== -@support.scrape -def genres(item): - support.info('genres',item) - - action = 'peliculas' - if item.args == 'genres': - patronBlock = r'<ul class="listSubCat" id="Film">(?P<block>.*)<ul class="listSubCat" id="Anno">' - elif item.args == 'years': - patronBlock = r'<ul class="listSubCat" id="Anno">(?P<block>.*)<ul class="listSubCat" id="Qualita">' - elif item.args == 'quality': - patronBlock = r'<ul class="listSubCat" id="Qualita">(?P<block>.*)<blockquote' - elif item.args == 'lucky': # sono i titoli random nella pagina - patronBlock = r'FILM RANDOM.*?class="listSubCat">(?P<block>.*)</ul>' - action = 'findvideos' - patronMenu = r'<li><a href="(?P<url>[^"]+)">(?P<title>[^<]+)<' - - #debug = True - return locals() - -# =========== def per cercare film/serietv ============= -#host+/index.php?do=search&story=avatar&subaction=search -def search(item, text): - support.info('search', item) - itemlist = [] - text = text.replace(" ", "+") - item.url = host+"/index.php?do=search&story=%s&subaction=search" % (text) - try: - return peliculas(item) - # Se captura la excepcion, para no interrumpir al buscador global si un canal falla - except: - import sys - for line in sys.exc_info(): - logger.error("%s" % line) - return [] - -# =========== def per le novità nel menu principale ============= - -def newest(categoria): - support.info('newest', categoria) - itemlist = [] - item = Item() - try: - if categoria == "peliculas": - item.url = host - item.action = "peliculas" - item.contentType='movie' - itemlist = peliculas(item) - - if itemlist[-1].action == "peliculas": - itemlist.pop() - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - logger.error("{0}".format(line)) - return [] - - return itemlist - -def findvideos(item): - support.info('findvideos', item) - return support.server(item, support.match(item, patron='<ul class="playernav">.*?</ul>', headers=headers).match) diff --git a/channels/animeforce.py b/channels/animeforce.py index d3ddf1ba..33aba3ec 100644 --- a/channels/animeforce.py +++ b/channels/animeforce.py @@ -74,20 +74,15 @@ def search(item, text): def peliculas(item): search = item.search anime = True - # debug = True - if 'movie' in item.url: - action = 'findvideos' - else: - action = 'check' + action = 'check' - # if not item.args: - # pagination = '' - # patron = r'<a\s*href="(?P<url>[^"]+)"\s*title="(?P<title>[^"]+)">' - # else: patron = r'<a href="(?P<url>[^"]+)"[^>]+>\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.*?)(?: Sub| sub| SUB|")' + if search: + patron = r'<a href="(?P<url>[^"]+)"\s*title="(?P<title>.*?)(?: Sub| sub| SUB|")' + if item.args == 'newest': item.action = 'findvideos' - + patronNext = '<li class="page-item disabled">(?:[^>]+>){4}<a class="page-link" href="([^"]+)' def itemHook(item): @@ -100,7 +95,7 @@ def peliculas(item): def check(item): - m = support.match(item, headers=headers, patron=r'Tipologia[^>]+><a href="([^"]+)"') + m = support.match(item, headers=headers, patron=r'Tipologia[^>]+>\s*<a href="([^"]+)"') item.data = m.data if 'movie' in m.match: item.contentType = 'movie' @@ -112,6 +107,7 @@ def check(item): @support.scrape def episodios(item): anime = True + pagination = 50 data = item.data if '<h6>Streaming</h6>' in data: @@ -130,30 +126,37 @@ def episodios(item): def findvideos(item): support.info(item) itemlist = [] - - if 'adf.ly' in item.url: - from servers.decrypters import adfly - url = adfly.get_long_url(item.url) - - elif 'bit.ly' in item.url: - url = support.httptools.downloadpage(item.url, only_headers=True, follow_redirects=False).headers.get("location") - + if item.data: + url = support.match(item.data, patron=r'<a\s*href="([^"]+)"\s*title="[^"]+"\s*class="btn btn-dark mb-1">').match else: - url = host - for u in item.url.split('/'): - if u and 'animeforce' not in u and 'http' not in u: - url += '/' + u + url = item.url - if 'php?' in url: - url = support.httptools.downloadpage(url, only_headers=True, follow_redirects=False).headers.get("location") - url = support.match(url, patron=r'class="button"><a href=(?:")?([^" ]+)', headers=headers).match - else: - if item.data: url = item.data - url = support.match(url, patron=r'data-href="([^"]+)" target').match - if not url: url = support.match(url, patron=[r'<source src=(?:")?([^" ]+)',r'name="_wp_http_referer" value="([^"]+)"']).match - if url.startswith('//'): url = 'https:' + url - elif url.startswith('/'): url = 'https:/' + url - if 'vvvvid' in url: itemlist.append(item.clone(action="play", title='VVVVID', url=url, server='vvvvid')) - else: itemlist.append(item.clone(action="play", title=support.config.get_localized_string(30137), url=url, server='directo')) + # if 'adf.ly' in item.url: + # from servers.decrypters import adfly + # url = adfly.get_long_url(item.url) + + # elif 'bit.ly' in item.url: + # url = support.httptools.downloadpage(item.url, only_headers=True, follow_redirects=False).headers.get("location") + + # else: + # url = host + # for u in item.url.split('/'): + # if u and 'animeforce' not in u and 'http' not in u: + # url += '/' + u + + + # if 'php?' in url: + # url = support.httptools.downloadpage(url, only_headers=True, follow_redirects=False).headers.get("location") + # url = support.match(url, patron=r'class="button"><a href=(?:")?([^" ]+)', headers=headers).match + # else: + # if item.data: url = item.data + # if item.contentType == 'movie': url = support.match() + # url = support.match(url, patron=r'data-href="([^"]+)" target').match + # if not url: url = support.match(url, patron=[r'<source src=(?:")?([^" ]+)',r'name="_wp_http_referer" value="([^"]+)"']).match + # if url.startswith('//'): url = 'https:' + url + # elif url.startswith('/'): url = 'https:/' + url + url = support.match(url, patron=r'data-href="([^"]+)" target').match + if 'vvvvid' in url: itemlist.append(item.clone(action="play", title='VVVVID', url=url, server='vvvvid')) + else: itemlist.append(item.clone(action="play", title=support.config.get_localized_string(30137), url=url, server='directo')) return support.server(item, itemlist=itemlist) diff --git a/channels/animeleggendari.json b/channels/animeleggendari.json deleted file mode 100644 index ec85dc22..00000000 --- a/channels/animeleggendari.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "animeleggendari", - "name": "AnimePerTutti", - "active": false, - "language": ["ita", "sub-ita"], - "thumbnail": "animepertutti.png", - "bannermenu": "animepertutti.png", - "categories": ["anime", "vos"], - "not_active":["include_in_newest_peliculas", "include_in_newest_series", "include_in_newest_anime"], - "settings": [] -} diff --git a/channels/animeleggendari.py b/channels/animeleggendari.py deleted file mode 100644 index 0eb86e6f..00000000 --- a/channels/animeleggendari.py +++ /dev/null @@ -1,141 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per animeleggendari -# ------------------------------------------------------------ - -from core import support -from lib.js2py.host import jsfunctions - -host = support.config.get_channel_url() - -headers = [['User-Agent', 'Mozilla/50.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0'], - ['Referer', host]] - - - - - -@support.menu -def mainlist(item): - - anime = [ - # ('Leggendari', ['/category/anime-leggendari/', 'peliculas']), - ('ITA', ['/category/anime-ita/', 'peliculas']), - ('SUB-ITA', ['/category/anime-sub-ita/', 'peliculas']), - ('Conclusi', ['/category/serie-anime-concluse/', 'peliculas']), - ('in Corso', ['/category/serie-anime-in-corso/', 'peliculas']), - ('Genere', ['', 'genres']) - ] - - return locals() - - -def search(item, texto): - support.info(texto) - - item.url = host + "/?s=" + texto - try: - 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 [] - - -@support.scrape -def genres(item): - blacklist = ['Contattaci','Privacy Policy', 'DMCA'] - patronMenu = r'<a href="(?P<url>[^"]+)">(?P<title>[^<]+)<' - patronBlock = r'Generi</a>\s*<ul[^>]+>(?P<block>.*?)<\/ul>' - action = 'peliculas' - return locals() - - -@support.scrape -def peliculas(item): - anime = True - blacklist = ['top 10 anime da vedere'] - if item.url != host: patronBlock = r'<div id="main-content(?P<block>.*?)<aside' - patron = r'<figure class="(?:mh-carousel-thumb|mh-posts-grid-thumb)">\s*<a (?:class="[^"]+" )?href="(?P<url>[^"]+)" title="(?P<title>.*?)(?: \((?P<year>\d+)\))? (?:(?P<lang>SUB ITA|ITA))(?: (?P<title2>[Mm][Oo][Vv][Ii][Ee]))?[^"]*"><img (?:class="[^"]+"|width="[^"]+" height="[^"]+") src="(?P<thumb>[^"]+)"[^>]+' - def itemHook(item): - if 'movie' in item.title.lower(): - item.title = support.re.sub(' - [Mm][Oo][Vv][Ii][Ee]|[Mm][Oo][Vv][Ii][Ee]','',item.title) - item.title += support.typo('Movie','_ () bold') - item.contentType = 'movie' - item.action = 'findvideos' - return item - def itemlistHook(itemlist): - itlist = [] - for item in itemlist: - if 'nuovo episodio:' not in item.title.lower(): - itlist += [item] - return itlist - - patronNext = r'<a class="next page-numbers" href="([^"]+)">' - action = 'episodios' - return locals() - - -@support.scrape -def episodios(item): - data = support.match(item, headers=headers, patronBlock=r'entry-content clearfix">(.*?)class="mh-widget mh-posts-2 widget_text').block - if not 'pagination clearfix' in data: - support.info('NOT IN DATA') - patron = r'<iframe.*?src="(?P<url>[^"]+)"' - title = item.title - def fullItemlistHook(itemlist): - if len(itemlist) > 0: - urls = [] - for item in itemlist: - urls.append(item.url) - item = itemlist[0] - item.data = urls - item.title = title - item.contentType = 'movie' - itemlist = [] - itemlist.append(item) - return itemlist - else: - url = item.url - anime = True - patronBlock = r'(?:<p style="text-align: left;">|<div class="pagination clearfix">\s*)(?P<block>.*?)</span></a></div>' - patron = r'(?:<a href="(?P<url>[^"]+)"[^>]+>)?<span class="pagelink">(?P<episode>\d+)' - def itemHook(item): - if not item.url: - item.url = url - if 'Movie Parte' in data: - item.title = support.typo(item.fulltitle + ' - Part ','bold') + item.title - item.contentType = 'movie' - else: - item.title = support.typo('Episodio ', 'bold') + item.title - return item - return locals() - -def check(item): - data = support.match(item, headers=headers).data - if 'Lista Episodi' not in data: - item.data = data - return findvideos(item) - - data = '' - return data - -def findvideos(item): - support.info() - if item.data: - data = item.data - else: - matches = support.match(item, patron=r'<iframe.*?src="(?P<url>[^"]+)"').matches - data = '' - if matches: - for match in matches: - try: data += str(jsfunctions.unescape(support.re.sub('@|g','%', match))) - except: data += '' - data += str(match) - else: - data = '' - - return support.server(item,data) diff --git a/channels/cineblog01.py b/channels/cineblog01.py index 26cfc954..64ce9996 100644 --- a/channels/cineblog01.py +++ b/channels/cineblog01.py @@ -9,14 +9,14 @@ from core import scrapertools, httptools, servertools, support from platformcode import logger, config -# def findhost(url): -# host = httptools.downloadpage(url, follow_redirect=True).url -# if host == 'https://cb01.uno/': -# host = support.match(host, patron=r'<a href="([^"]+)').match -# return host +def findhost(url): + host = httptools.downloadpage(url, follow_redirect=True).url + if host == 'https://cb01.uno/': + host = support.match(host, patron=r'<a href="([^"]+)').match + return host -host = config.get_channel_url() +host = config.get_channel_url(findhost) headers = [['Referer', host]] @@ -223,7 +223,7 @@ def findvideos(item): patronvideos = r'([\w.]+)</strong></div></td>' support.addQualityTag(item, itemlist, data, patronvideos) - return itemlist + return support.server(item, itemlist=itemlist) # Estrae i contenuti - Download # load_links(itemlist, '<strong>Download:</strong>(.*?)<tableclass=cbtable height=30>', "aqua", "Download") diff --git a/channels/cinemalibero.py b/channels/cinemalibero.py index 86a7dfeb..b0af89c1 100644 --- a/channels/cinemalibero.py +++ b/channels/cinemalibero.py @@ -7,6 +7,7 @@ import re from core import httptools, support, scrapertools from core.item import Item +from core.support import typo from platformcode import config import sys if sys.version_info[0] >= 3: @@ -57,11 +58,13 @@ def peliculas(item): patron = r'<div class="col-lg-3">[^>]+>[^>]+>\s<a href="(?P<url>[^"]+)".+?url\((?P<thumb>[^\)]+)\)">[^>]+>(?P<title>[^<]+)<[^>]+>[^>]+>(?:[^>]+>)?\s?(?P<rating>[\d\.]+)?[^>]+>.+?(?:[ ]\((?P<year>\d{4})\))?<[^>]+>[^>]+>(.?[\d\-x]+\s\(?(?P<lang>[sSuUbBiItTaA\-]+)?\)?\s?(?P<quality>[\w]+)?[|]?\s?(?:[fFiInNeE]+)?\s?\(?(?P<lang2>[sSuUbBiItTaA\-]+)?\)?)?' pagination = 25 elif item.contentType == 'movie': - patron = r'<a href="(?P<url>[^"]+)" title="(?P<title>.+?)(?:[ ]\[(?P<lang>[sSuUbB\-iItTaA]+)\])?(?:[ ]\((?P<year>\d{4})\))?"\s*alt="[^"]+"\s*class="[^"]+"(?: style="background-image: url\((?P<thumb>.+?)\)">)?\s*<div class="voto">[^>]+>[^>]+>.(?P<rating>[\d\.a-zA-Z\/]+)?[^>]+>[^>]+>[^>]+>(?:<div class="genere">(?P<quality>[^<]+)</div>)?' + # action = 'findvideos' + patron = r'<a href="(?P<url>[^"]+)" title="(?P<title>.+?)(?:[ ]\[(?P<lang>[sSuUbB\-iItTaA]+)\])?(?:[ ]\((?P<year>\d{4})?\))?"\s*alt="[^"]+"\s*class="[^"]+"(?: style="background-image: url\((?P<thumb>.+?)\)">)?\s*<div class="voto">[^>]+>[^>]+>.(?P<rating>[\d\.a-zA-Z\/]+)?[^>]+>[^>]+>[^>]+>(?:<div class="genere">(?P<quality>[^<]+)</div>)?' if item.args == 'update': patronBlock = r'<section id="slider">(?P<block>.*?)</section>' - patron = r'<a href="(?P<url>(?:https:\/\/.+?\/(?P<title>[^\/]+[a-zA-Z0-9\-]+)(?P<year>\d{4})))/".+?url\((?P<thumb>[^\)]+)\)">' + patron = r'<a href="(?P<url>(?:https:\/\/.+?\/(?P<title>[^\/]+[a-zA-Z0-9\-]+)(?P<year>\d{4})?))/".+?url\((?P<thumb>[^\)]+)\)">' elif item.contentType == 'tvshow': + # action = 'episodios' if item.args == 'update': patron = r'<a href="(?P<url>[^"]+)"[^<]+?url\((?P<thumb>.+?)\)">\s*?<div class="titolo">(?P<title>.+?)(?: – Serie TV)?(?:\([sSuUbBiItTaA\-]+\))?[ ]?(?P<year>\d{4})?</div>\s*?(?:<div class="genere">)?(?:[\w]+?\.?\s?[\s|S]?[\dx\-S]+?\s\(?(?P<lang>[iItTaA]+|[sSuUbBiItTaA\-]+)\)?\s?(?P<quality>[HD]+)?|.+?\(?(?P<lang2>[sSuUbBiItTaA\-]+)?\)?</div>)' pagination = 25 @@ -92,7 +95,7 @@ def peliculas(item): @support.scrape def episodios(item): data = item.data - # debug = True + # debugBlock = True if item.args == 'anime': support.info("Anime :", item) # blacklist = ['Clipwatching', 'Verystream', 'Easybytez', 'Flix555', 'Cloudvideo'] @@ -132,7 +135,7 @@ def episodios(item): with futures.ThreadPoolExecutor() as executor: for s in servers: executor.submit(get_ep, s) - ret.extend([it.clone(title=ep, contentSeason=int(ep.split('x')[0]), contentEpisodeNumber=int(ep.split('x')[1]), servers=[srv.tourl() for srv in episodes[ep]]) for ep in episodes]) + ret.extend([it.clone(title=ep+typo(it.contentLanguage, '_ [] color kod'), contentSeason=int(ep.split('x')[0]), contentEpisodeNumber=int(ep.split('x')[1]), servers=[srv.tourl() for srv in episodes[ep]]) for ep in episodes]) else: ret.append(it) return sorted(ret, key=lambda i: i.title) @@ -142,7 +145,6 @@ def episodios(item): @support.scrape def genres(item): - action='peliculas' patron_block=r'<div id="bordobar" class="dropdown-menu(?P<block>.*?)</li>' patronMenu=r'<a class="dropdown-item" href="(?P<url>[^"]+)" title="(?P<title>[A-z]+)"' @@ -203,11 +205,16 @@ def check(item): item.contentType = 'tvshow' item.args = 'anime' item.data = data - return episodios(item) + itemlist = episodios(item) + if not itemlist: + item.data = data + item.action = 'findvideos' + return findvideos(item) elif ck == 'film': item.contentType = 'movie' item.data = data + item.action = 'findvideos' return findvideos(item) else: @@ -217,8 +224,9 @@ def check(item): if not itemlist: item.contentType = 'movie' item.data = data + item.action = 'findvideos' return findvideos(item) - return itemlist + def findvideos(item): @@ -234,9 +242,27 @@ def findvideos(item): if item.servers: return support.server(item, itemlist=[Item().fromurl(s) for s in item.servers]) if not item.data: - item.data = support.match(item, patron='<p>\s*<strong>\s*<u>.*?</p>').match + item.data = httptools.downloadpage(item.url) + item.data = scrapertools.find_single_match(item.data, '<div class="at-above-post addthis_tool"(.*?)<div class="at-below-post') + servers = [] + if item.args == 'anime': + if item.urls: # this is a episode + return support.server(item, itemlist=[Item(url=support.unshortenit.FileCrypt().unshorten(u)) for u in item.urls]) + itemlist = [] + episodes = {} + # support.dbg() + for uri in support.unshortenit.FileCrypt().find(item.data): + for ep in support.unshortenit.FileCrypt(uri).list_files(): + ep = ('.'.join(ep[0].split('.')[:-1]), ep[1]) # remove extension + if not ep[0] in episodes: + episodes[ep[0]] = [] + episodes[ep[0]].append(ep[1]) + for ep in episodes.keys(): + itemlist.append(item.clone(title=ep, urls=episodes[ep], action='findvideos', data='')) + return itemlist total_servers = support.server(item, data=item.data) + if item.contentType == 'episode' and len(set([srv.server for srv in total_servers])) < len([srv.server for srv in total_servers]): # i link contengono più puntate, cerco quindi quella selezionata with futures.ThreadPoolExecutor() as executor: diff --git a/channels/discoveryplus.py b/channels/discoveryplus.py index 2d025a4f..5248b89c 100644 --- a/channels/discoveryplus.py +++ b/channels/discoveryplus.py @@ -67,7 +67,7 @@ def live(item): logger.debug() 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)) + itemlist.append(item.clone(title=typo(name,'bold'), fulltitle=name, plot=values['plot'], url=values['url'], id=values['id'], action='findvideos', forcethumb=True, no_return=True)) return support.thumb(itemlist, live=True) @@ -171,7 +171,7 @@ def episodios(item): fulltitle=title, plot=plot, id=episode['id'], - action='play', + action='findvideos', contentType='episode', season=option['id'], episode=episode['attributes']['episodeNumber'], @@ -182,7 +182,7 @@ def episodios(item): return itemlist -def play(item): +def findvideos(item): if item.livefilter: item.id = liveDict()[item.livefilter]['id'] item.fulltitle = item.livefilter @@ -198,4 +198,4 @@ def play(item): else: item.url = data['streaming']['hls']['url'] item.manifest = 'hls' - return [item] \ No newline at end of file + return support.server(item, itemlist=[item], Download=False, Videolibrary=False) \ No newline at end of file diff --git a/channels/dsda.json b/channels/dsda.json deleted file mode 100644 index 9ae3060f..00000000 --- a/channels/dsda.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "dsda", - "name": "D.S.D.A", - "language": ["ita"], - "active": false, - "thumbnail": "dsda.png", - "banner": "dsda.png", - "categories": ["documentary"], - "settings": [] -} diff --git a/channels/dsda.py b/channels/dsda.py deleted file mode 100644 index 71fe4ea5..00000000 --- a/channels/dsda.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per documentaristreamingda -# ------------------------------------------------------------ - -from core import support -from core.item import Item -from platformcode import logger, config - -host = config.get_channel_url() - -@support.menu -def mainlist(item): - docu = [('Documentari {bullet bold}',('/elenco-documentari','peliculas')), - ('Categorie {submenu}',('','menu')), - ('Cerca... {bullet bold}',('','search')),] - return locals() - - -@support.scrape -def menu(item): - action = 'peliculas' - patronMenu = r'<li class="menu-item menu-item-type-taxonomy[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^<]+)<' - def fullItemlistHook(itemlist): - item_list = [] - title_list = [] - for item in itemlist: - if item.title not in title_list: - item_list.append(item) - title_list.append(item.title) - itemlist = item_list - return itemlist - return locals() - -def newest(categoria): - support.info() - item = Item() - try: - if categoria == "documentales": - item.url = host + "/elenco-documentari" - item.action = "peliculas" - return peliculas(item) - - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.logger.error("{0}".format(line)) - return [] - - -def search(item, texto): - support.info(texto) - item.url = host + "/?s=" + texto - try: - return peliculas(item) - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - logger.error("%s" % line) - return [] - - -@support.scrape -def peliculas(item): - blacklist = ['GUIDA PRINCIPIANTI Vedere film e documentari streaming gratis', 'Guida Dsda'] - data = support.match(item).data - # debug =True - if item.args == 'collection': - if 'class="panel"' in data: - item.args = 'raccolta' - patron = r'class="title-episodio">(?P<title>[^<]+)<(?P<url>.*?)<p' - # patron = r'<a (?:style="[^"]+" )?href="(?P<url>[^"]+)"[^>]+>(?:[^>]+><strong>)?(?P<title>[^<]+)(?:</a>)?</strong' - else: - patron = r'<div class="cover-racolta">\s*<a href="(?P<url>[^"]+)"[^>]+>\s*<img width="[^"]+" height="[^"]+" src="(?P<thumb>[^"]+)".*?<p class="title[^>]+>(?P<title>[^<]+)<' - else: - patron = r'<article[^>]+>[^>]+>[^>]+>(?:<img width="[^"]+" height="[^"]+" src="(?P<thumb>[^"]+)"[^>]+>)?.*?<a href="(?P<url>[^"]+)"[^>]*>\s*(?P<title>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<p>(?P<plot>[^<]+)<' - patronNext = r'<a class="page-numbers next" href="([^"]+)">' - - # select category - def itemHook(item): - title = support.re.sub(r'(?:[Ss]erie\s*|[Ss]treaming(?:\s*[Dd][Aa])?\s*|[Cc]ollezione\s*|[Rr]accolta\s*|[Dd]ocumentari(?:o)?\s*)?','',item.fulltitle).strip() - if 'serie' in item.fulltitle.lower(): - item.contentType = 'tvshow' - item.action = 'episodios' - item.contentSerieName = title - item.contentTitle = '' - elif 'collezion' in item.fulltitle.lower() or \ - 'raccolt' in item.fulltitle.lower() or \ - 'filmografia' in item.fulltitle.lower(): - item.args = 'collection' - item.action = 'peliculas' - item.contentTitle = title - item.contentSerieName = '' - else: - item.contentTitle = title - item.contentSerieName = '' - - item.title = support.typo(title,'bold') - item.fulltitle = item.show = title - return item - # remove duplicates - def fullItemlistHook(itemlist): - item_list = [] - title_list = [] - for item in itemlist: - if item.title not in title_list: - item_list.append(item) - title_list.append(item.title) - itemlist = item_list - return itemlist - return locals() - -@support.scrape -def episodios(item): - html = support.match(item, patron=r'class="title-episodio">(\d+x\d+)') - data = html.data - if html.match: - patron = r'class="title-episodio">(?P<episode>[^<]+)<(?P<url>.*?)<p' - else: - patron = r'class="title-episodio">(?P<title>[^<]+)<(?P<url>.*?)<p' - - # def itemlistHook(itemlist): - # counter = 0 - # for item in itemlist: - # episode = support.match(item.title, patron=r'\d+').match - # if episode == '1': - # counter += 1 - # item.title = support.typo(str(counter) + 'x' + episode.zfill(2) + support.re.sub(r'\[[^\]]+\](?:\d+)?','',item.title),'bold') - # return itemlist - return locals() - - -def findvideos(item): - support.info() - if item.args == 'raccolta' or item.contentType == 'episode': - return support.server(item, item.url) - else: - return support.server(item) \ No newline at end of file diff --git a/channels/fastsubita.json b/channels/fastsubita.json deleted file mode 100644 index bcca9544..00000000 --- a/channels/fastsubita.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "fastsubita", - "name": "Fastsubita", - "language": ["sub-ita"], - "active": false, - "thumbnail": "fastsubita.png", - "banner": "fastsubita.png", - "categories": ["tvshow", "vos"], - "not_active": ["include_in_newest_peliculas", "include_in_newest_anime"], - "settings": [] -} diff --git a/channels/fastsubita.py b/channels/fastsubita.py deleted file mode 100644 index c3cfe75f..00000000 --- a/channels/fastsubita.py +++ /dev/null @@ -1,214 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per fastsubita.py -# ------------------------------------------------------------ -""" - - Su questo canale, nella categoria 'Ricerca Globale' - non saranno presenti le voci 'Aggiungi alla Videoteca' - e 'Scarica Film'/'Scarica Serie', dunque, - la loro assenza, nel Test, NON dovrà essere segnalata come ERRORE. - - Novità. Indicare in quale/i sezione/i è presente il canale: - - serie - - Ulteriori info: - - SOLO SUB-ITA - -""" -from core import support, httptools, scrapertools -from core.item import Item -from core.support import info -from platformcode import config - -host = config.get_channel_url() -headers = [['Referer', host]] - - -@support.menu -def mainlist(item): - - Tvshow = [ - ('Aggiornamenti', ['', 'peliculas', 'update']), - ('Cerca... {bold}{TV}', ['', 'search']) - ] - - # search = '' - - return locals() - - -@support.scrape -def peliculas(item): - support.info(item) - # support.dbg() - deflang = 'Sub-ITA' - - # è una singola pagina con tutti gli episodi - if item.grouped and not support.scrapertools.find_single_match(item.url, '-[0-9]+x[0-9]+-'): - item.grouped = False - return episodios_args(item) - - # ogni puntata è un articolo a se - if item.fulltitle: - item.url = host + '?s=' + item.fulltitle - actLike = 'episodios' - - action = 'findvideos' - blacklist = [''] - if item.args == 'genres': - patronBlock = r'<h4 id="mctm1-.">'+item.fulltitle+'</h4>(?P<block>.+?)</div>' - patron = r'[^>]+>[^>]+>.+?href="(?P<url>[^"]+)[^>]>(?P<title>[^<]+)\s<' - action = 'episodios' - elif item.args == 'search': - group = True - patronBlock = r'</header>(?P<block>.*?)</main>' - patron = '(?:<img[^>]+src="(?P<thumb>[^"]+)".*?)?<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^<]+?)(?:(?P<episode>\d+×\d+|\d+×\d+)|\[[sS](?P<season>[0-9]+)[^]]+\])\s?(?:(?P<lang>\([a-zA-Z\s]+\)) (?:[Ss]\d+[Ee]\d+)?\s?(?:[&#\d;|.{3}]+)(?P<title2>[^”[<]+)(?:&#\d)?)?' - else: - # è una singola pagina con tutti gli episodi - if item.args != 'update' and not support.scrapertools.find_single_match(item.url, '-[0-9]+x[0-9]+-'): - return episodios_args(item) - patron = r'<div class="featured-thumb"> +<a href="(?P<url>[^"]+)" title="(?P<title>[^[]+)\[(?P<episode>\d+×\d+)?' - patronBlock = r'<main id="main"[^>]+>(?P<block>.*?)<div id="secondary' - - # def itemlistHook(itemlist): - # from core import scraper - # return scraper.sort_episode_list(itemlist) - - patronNext = '<a class="next page-numbers" href="(.*?)">Successivi' - - # debug = True - return locals() - - -def episodios_args(item): - actLike = 'episodios' - # support.dbg() - - deflang = 'Sub-ITA' - action = 'findvideos' - patron = '(?P<episode>\d+×\d+|\d+[×.]+\d+)(?:\s?\((?P<lang>[a-zA-Z ]+)\))?(?:\s[Ss]\d+[Ee]+\d+)? +(?:“|“)(?P<title2>.*?)(?:”|”).*?(?P<other>.*?)(?:/>|<p)' - patronBlock = r'<main id="main" class="site-main" role="main">(?P<block>.*?)</main>' - patronNext = '<a class="next page-numbers" href="(.*?)">Successivi' - - # debug = True - return locals() - - -@support.scrape -def episodios(item): - support.info(item) - return episodios_args(item) - - -@support.scrape -def genres(item): - support.info() - #support.dbg() - - action = 'peliculas' - patronBlock = r'<div id="mcTagMapNav">(?P<block>.+?)</div>' - patron = r'<a href="(?P<url>[^"]+)">(?P<title>.+?)</a>' - - def itemHook(item): - item.url = host+'/elenco-serie-tv/' - item.contentType = 'tvshow' - return item - - #debug = True - return locals() - - -def search(item, text): - support.info('search', item) - text = text.replace(' ', '+') - item.url = host + '?s=' + text - try: - item.args = 'search' - item.contentType = 'tvshow' - return peliculas(item) - # Se captura la excepcion, para no interrumpir al buscador global si un canal falla - except: - import sys - for line in sys.exc_info(): - info('search log:', line) - return [] - - -def newest(categoria): - support.info('newest ->', categoria) - itemlist = [] - item = Item() - if categoria == 'series': - try: - item.contentType = 'tvshow' - item.args = 'newest' - item.url = host - item.action = 'peliculas' - itemlist = peliculas(item) - - if itemlist[-1].action == 'peliculas': - itemlist.pop() - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.info('newest log: ', line) - return [] - - return itemlist - - -def findvideos(item): - support.info('findvideos ->', item) - patron = r'<a href="([^"]+)">' - - itemlist = [] - if item.other.startswith('http'): - resp = httptools.downloadpage(item.url, follow_redirects=False) - data = resp.headers.get("location", "") + '\n' - elif item.other: - html = support.match(item.other, patron=patron, headers=headers) - matches = html.matches - data = html.data - for scrapedurl in matches: - if 'is.gd' in scrapedurl: - resp = httptools.downloadpage(scrapedurl, follow_redirects=False) - data += resp.headers.get("location", "") + '\n' - elif not support.scrapertools.find_single_match(item.url, '-[0-9]+x[0-9]+-'): - return episodios(item) - else: - patronBlock = '<div class="entry-content">(?P<block>.*)<footer class="entry-footer">' - html = support.match(item, patron=patron, patronBlock=patronBlock, headers=headers) - matches = html.matches - data= html.data - - if item.args != 'episodios': - item.infoLabels['mediatype'] = 'episode' - for scrapedurl in matches: - if 'is.gd' in scrapedurl: - resp = httptools.downloadpage(scrapedurl, follow_redirects=False) - data += resp.headers.get("location", "") + '\n' - - itemlist += support.server(item, data) - - # data = support.match(item.url).data - # patron = r'>Posted in <a href="https?://fastsubita.com/serietv/([^/]+)/(?:[^"]+)?"' - # series = scrapertools.find_single_match(data, patron) - # titles = support.typo(series.upper().replace('-', ' '), 'bold color kod') - # goseries = support.typo("Vai alla Serie:", ' bold color kod') - # itemlist.append( - # item.clone(channel=item.channel, - # # title=goseries + titles, - # title=titles, - # fulltitle=titles, - # show=series, - # contentType='tvshow', - # contentSerieName=series, - # url=host+"/serietv/"+series, - # action='episodios', - # contentTitle=titles, - # plot = "Vai alla Serie " + titles + " con tutte le puntate", - # )) - - return itemlist diff --git a/channels/film4k.json b/channels/film4k.json deleted file mode 100644 index 2875fcfa..00000000 --- a/channels/film4k.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "film4k", - "name": "Film4k", - "language": ["ita"], - "active": false, - "thumbnail": "film4k.png", - "banner": "film4k.png", - "categories": ["tvshow", "movie", "anime"], - "not_active": ["include_in_newest_peliculas", "include_in_newest_anime", "include_in_newest_series"], - "settings": [] -} diff --git a/channels/film4k.py b/channels/film4k.py deleted file mode 100644 index 3e82f3b3..00000000 --- a/channels/film4k.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per film4k -# ------------------------------------------------------------ - -from core import support -from platformcode import logger, config - - -def findhost(url): - return support.httptools.downloadpage(url).url - -host = config.get_channel_url(findhost) - - -@support.menu -def mainlist(item): - - film = ['movies', - ('Qualità', ['', 'menu', 'quality']), - ('Generi', ['movies', 'menu', 'genres']), - ('Anno', ['movies', 'menu', 'releases']), - ('Più popolari', ['trending/?get=movies', 'peliculas']), - ('Più votati', ['ratings/?get=movies', 'peliculas'])] - tvshow = ['/tvshows', - ('Più popolari', ['trending/?get=tv', 'peliculas']), - ('Più votati', ['ratings/?get=tv', 'peliculas'])] - return locals() - - -def search(item, text): - logger.info('search', text) - item.url = item.url + "/?s=" + text - try: - return support.dooplay_search(item) - except: - import sys - for line in sys.exc_info(): - logger.error("%s" % line) - return [] - - - -def peliculas(item): - if 'anime' in item.url: - return support.dooplay_peliculas(item, True) - else: - return support.dooplay_peliculas(item, False) - - -def episodios(item): - itemlist = support.dooplay_get_episodes(item) - return itemlist - - -def findvideos(item): - itemlist = [] - if item.contentType == 'episode': - linkHead = support.httptools.downloadpage(item.url, only_headers=True).headers['link'] - epId = support.scrapertools.find_single_match(linkHead, r'\?p=([0-9]+)>') - for link in support.dooplay_get_links(item, host, paramList=[['tv', epId, 1, 'title', 'server']]): - itemlist.append( - item.clone(action="play", url=link['url'])) - else: - for link, quality in support.match(item.url, patron="(" + host + """links/[^"]+).*?class="quality">([^<]+)""").matches: - srv = support.servertools.find_video_items(data=support.httptools.downloadpage(link).data) - for s in srv: - s.quality = quality - itemlist.extend(srv) - return support.server(item, itemlist=itemlist) - - -@support.scrape -def menu(item): - action = 'peliculas' - if item.args in ['genres','releases']: - patronBlock = r'<nav class="' + item.args + r'">(?P<block>.*?)</nav' - patronMenu= r'<a href="(?P<url>[^"]+)"[^>]*>(?P<title>[^<]+)<' - else: - patronBlock = r'class="main-header">(?P<block>.*?)headitems' - patronMenu = r'(?P<url>' + host + r'quality/[^/]+/\?post_type=movies)">(?P<title>[^<]+)' - return locals() diff --git a/channels/filmigratis.json b/channels/filmigratis.json deleted file mode 100644 index 88221ecc..00000000 --- a/channels/filmigratis.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "id": "filmigratis", - "name": "Filmi Gratis", - "active": false, - "language": ["ita", "sub-ita"], - "thumbnail": "filmigratis.png", - "banner": "filmigratis.png", - "categories": ["movie","tvshow"], - "settings": [ - { - "id": "include_in_newest_peliculas", - "type": "bool", - "label": "@70727", - "default": false, - "enabled": false, - "visible": false - }, - { - "id": "include_in_newest_series", - "type": "bool", - "label": "@70727", - "default": false, - "enabled": false, - "visible": false - }, - { - "id": "include_in_newest_anime", - "type": "bool", - "label": "@70727", - "default": false, - "enabled": false, - "visible": false - } - ] -} diff --git a/channels/filmigratis.py b/channels/filmigratis.py deleted file mode 100644 index 22ec19da..00000000 --- a/channels/filmigratis.py +++ /dev/null @@ -1,156 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per Filmi Gratis -# ------------------------------------------------------------ -""" - La voce "Al cinema" si riferisce ai titoli che scorrono nella home page - - Problemi: - - Nessuno noto - - Novità, il canale, è presente in: - - FILM -""" -import re - -from core import httptools, support -from core.item import Item -from platformcode import config - -host = config.get_channel_url() - - - - -headers = [['Referer', host]] - - -@support.menu -def mainlist(item): - film = [ - ('Al Cinema ', ['', 'peliculas', 'cinema']), - ('Categorie', ['', 'genres', 'genres']), - ] - - tvshow = ['/serie/ALL', - ('Generi', ['', 'genres', 'genres']) - ] - - search = '' - return locals() - -@support.scrape -def peliculas(item): - support.info() - - if item.args == 'search': - action = '' - patron = r'<div class="cnt">.*?src="([^"]+)"[^>]+>[^>]+>[^>]+>\s+(?P<title>.+?)(?:\[(?P<lang>Sub-ITA|SUB-ITA|SUB)\])?\s?(?:\[?(?P<quality>HD).+\]?)?\s?(?:\(?(?P<year>\d+)?\)?)?\s+<[^>]+>[^>]+>[^>]+>\s<a href="(?P<url>[^"]+)"[^<]+<' - patronBlock = r'<div class="container">(?P<block>.*?)</main>' - elif item.contentType == 'movie': - if not item.args: - # voce menu: Film - patronBlock = r'<h1>Film streaming ita in alta definizione</h1>(?P<block>.*?)<div class="content-sidebar">' - patron = r'<div class="timeline-right">[^>]+>\s<a href="(?P<url>.*?)".*?src="(?P<thumb>.*?)".*?<h3 class="timeline-post-title">(?:(?P<title>.+?)\s\[?(?P<lang>Sub-ITA)?\]?\s?\[?(?P<quality>HD)?\]?\s?\(?(?P<year>\d+)?\)?)<' - patronNext = r'<a class="page-link" href="([^"]+)">>' - elif item.args == 'cinema': - patronBlock = r'<div class="owl-carousel" id="postCarousel">(?P<block>.*?)<section class="main-content">' - patron = r'background-image: url\((?P<thumb>.*?)\).*?<h3.*?>(?:(?P<title>.+?)\s\[?(?P<lang>Sub-ITA)?\]?\s?\[?(?P<quality>HD)?\]?\s?\(?(?P<year>\d+)?\)?)<.+?<a.+?<a href="(?P<url>[^"]+)"[^>]+>' - elif item.args == 'genres': - # ci sono dei titoli dove ' viene sostituito con " da support - data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data - data = re.sub('\n|\t', ' ', data) - patron = r'<div class="cnt">\s.*?src="([^"]+)".+?title="((?P<title>.+?)(?:[ ]\[(?P<lang>Sub-ITA|SUB-ITA)\])?(?:[ ]\[(?P<quality>.*?)\])?(?:[ ]\((?P<year>\d+)\))?)"\s*[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s+<a href="(?P<url>[^"]+)"' - patronBlock = r'<div class="container">(?P<block>.*?)</main>' - pagination = '' - - patronNext = '<a class="page-link" href="([^"]+)">>>' - else: - action = 'episodios' - patron = r'<div class="cnt">\s.*?src="([^"]+)".+?title="((?P<title>.+?)(?:[ ]\[(?P<lang>Sub-ITA|SUB-ITA)\])?(?:[ ]\[(?P<quality>.*?)\])?(?:[ ]\((?P<year>\d+)\))?)"\s*[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s+<a href="(?P<url>[^"]+)"' -## if item.args == 'search': -## patron = r'<div class="cnt">.*?src="([^"]+)".+?[^>]+>[^>]+>[^>]+>\s+((?P<title>.+?)(?:[ ]\[(?P<lang>Sub-ITA|SUB-ITA)\])?(?:[ ]\[(?P<quality>.*?)\])?(?:[ ]\((?P<year>\d+)\))?)\s+<[^>]+>[^>]+>[^>]+>[ ]<a href="(?P<url>[^"]+)"' - patronBlock = r'<div class="container">(?P<block>.*?)</main>' - - def itemHook(item): - if item.args == 'search': - if 'series' in item.url: - item.action = 'episodios' - item.contentType = 'tvshow' - else: - item.action = 'findvideos' - item.contentType = 'movie' - return item - - #debug = True - return locals() - - -@support.scrape -def episodios(item): - support.info() - - action = 'findvideos' - patronBlock = r'<div class="row">(?P<block>.*?)<section class="main-content">' - patron = r'href="(?P<url>.*?)">(?:.+?)?\s+S(?P<season>\d+)\s\-\sEP\s(?P<episode>\d+)[^<]+<' - - return locals() - -@support.scrape -def genres(item): - support.info() - - if item.contentType == 'movie': - action = 'peliculas' - patron = r'<a href="(?P<url>.*?)">(?P<title>.*?)<' - patronBlock = r'CATEGORIES.*?<ul>(?P<block>.*?)</ul>' - else: - item.contentType = 'tvshow' - action = 'peliculas' - blacklist = ['Al-Cinema'] - patron = r'<a href="(?P<url>.*?)">(?P<title>.*?)<' - patronBlock = r'class="material-button submenu-toggle"> SERIE TV.*?<ul>.*?</li>(?P<block>.*?)</ul>' - - return locals() - - -def search(item, text): - support.info('search', item) - - text = text.replace(' ', '+') - item.url = host + '/search/?s=' + text - try: - item.args = 'search' - return peliculas(item) - # Se captura la excepcion, para no interrumpir al buscador global si un canal falla - except: - import sys - for line in sys.exc_info(): - support.info('search log:', line) - return [] - -def newest(categoria): - support.info('newest ->', categoria) - itemlist = [] - item = Item() - try: - if categoria == 'peliculas': - item.url = host - item.contentType = 'movie' - item.action = 'peliculas' - itemlist = peliculas(item) - - if itemlist[-1].action == 'peliculas': - itemlist.pop() - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.info({0}.format(line)) - return [] - - return itemlist - -def findvideos(item): - support.info() - return support.server(item) diff --git a/channels/guardaseriecam.py b/channels/guardaseriecam.py index cdab2da3..9b6ecfe4 100644 --- a/channels/guardaseriecam.py +++ b/channels/guardaseriecam.py @@ -35,8 +35,9 @@ def list(item): @support.scrape def peliculas(item): + # debug = True patron = r'<div class="mlnh-thumb"><a href="(?P<url>[^"]+).*?title="(?P<title>[^"]+).*?src="(?P<thumb>[^"]+).*?hdn">(?P<year>[0-9]{4})' - patronNext = 'pagenavi.*?<span>.</span>.*?<a href="([^"]+)' + patronNext = 'pagenavi.*?<a href="([^"]+)">\d+' action = 'episodios' return locals() diff --git a/channels/guardaserieicu.py b/channels/guardaserieicu.py index 44f8dd48..8d205583 100644 --- a/channels/guardaserieicu.py +++ b/channels/guardaserieicu.py @@ -26,7 +26,7 @@ def mainlist(item): @support.scrape def peliculas(item): - debug = True + # debug = True # patronBlock = r'movies-list movies-list-full(?P<block>.*?)footer>' if item.args == 'search': patron = r'<div data-movie-id[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>(?:\s*<span class="mli-quality">(?P<quality>[^>]+)</span>)?\s*<img src="(?P<thumbnail>[^"]+)[^>]+>[^>]+>[^>]+>(?P<title>[^<]+).*?jt-info[^>]+>[^:]+:\s*(?P<rating>[^<]+)[^>]+>[^>]+>[^>]+>(?P<year>\d*)[^>]+>[^>]+>[^>]+>(?P<duration>\d*).*?"f-desc">(?:\s*<p>(?P<plot>[^<]+))?' diff --git a/channels/la7.py b/channels/la7.py index 3097fd70..fce2d748 100644 --- a/channels/la7.py +++ b/channels/la7.py @@ -34,8 +34,8 @@ 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)] + itemlist = [item.clone(title=support.typo('La7', 'bold'), fulltitle='La7', url= host + '/dirette-tv', action='findvideos', forcethumb = True, no_return=True), + item.clone(title=support.typo('La7d', 'bold'), fulltitle='La7d', url= host + '/live-la7d', action='findvideos', forcethumb = True, no_return=True)] return support.thumb(itemlist, live=True) @@ -57,7 +57,7 @@ def replay_menu(item): @support.scrape def replay(item): - action = 'play' + action = 'findvideos' patron = r'guida-tv"><[^>]+><[^>]+>(?P<hour>[^<]+)<[^>]+><[^>]+><[^>]+>\s*<a href="(?P<url>[^"]+)"><[^>]+><div class="[^"]+" data-background-image="(?P<t>[^"]+)"><[^>]+><[^>]+><[^>]+><[^>]+>\s*(?P<name>[^<]+)<[^>]+><[^>]+><[^>]+>(?P<plot>[^<]+)<' def itemHook(item): item.title = support.typo(item.hour + ' - ' + item.name,'bold') @@ -99,7 +99,7 @@ def peliculas(item): def episodios(item): data = support.match(item).data # debug = True - action = 'play' + action = 'findvideos' if '>puntate<' in data: patronBlock = r'>puntate<(?P<block>.*?)home-block-outbrain' url = support.match(data, patron=r'>puntate<[^>]+>[^>]+>[^>]+><a href="([^"]+)"').match @@ -127,7 +127,7 @@ def episodios(item): return locals() -def play(item): +def findvideos(item): support.info() if item.livefilter: for it in live(item): @@ -169,5 +169,6 @@ def play(item): match = support.match(data, patron='/content/entry/data/(.*?).mp4').match if match: url = 'https://awsvodpkg.iltrovatore.it/local/hls/,/content/entry/data/' + support.match(item, patron='/content/entry/data/(.*?).mp4').match + '.mp4.urlset/master.m3u8' - item = item.clone(title='Direct', url=url, server='directo', action='play') - return support.servertools.find_video_items(item, data=url) + + item = item.clone(title='Direct', server='directo', url=url, action='play') + return support.server(item, itemlist=[item], Download=False, Videolibrary=False) diff --git a/channels/mediasetplay.json b/channels/mediasetplay.json index e92fc4e5..3b74b0fd 100644 --- a/channels/mediasetplay.json +++ b/channels/mediasetplay.json @@ -1,10 +1,10 @@ { "id": "mediasetplay", - "name": "Mediaset Play", + "name": "Mediaset play infinity [free]", "active": true, "language": ["ita"], - "thumbnail": "mediasetplay.png", - "banner": "mediasetplay.png", + "thumbnail": "mediasetplayinfinity.png", + "banner": "mediasetplayinfinity.png", "categories": ["movie", "tvshow", "documentary", "live"], "not_active": ["include_in_newest"], "default_off": ["include_in_global_search"], diff --git a/channels/mediasetplay.py b/channels/mediasetplay.py index af8721c0..fcfe176b 100644 --- a/channels/mediasetplay.py +++ b/channels/mediasetplay.py @@ -95,7 +95,7 @@ def live(item): urls=guide['tuningInstruction']['urn:theplatform:tv:location:any'], plot=plot, url=url, - action='play', + action='findvideos', thumbnail=thumb, forcethumb=True)) @@ -141,7 +141,7 @@ def peliculas(item): else: contentType = 'movie' video_id = it['guid'] - action = 'play' + action = 'findvideos' for k, v in it['thumbnails'].items(): if 'image_vertical' in k and not thumb: thumb = v['url'].replace('.jpg', '@3.jpg') @@ -228,13 +228,13 @@ def episodios(item): thumbnail=thumb, forcethumb=True, contentType='episode', - action='play', + action='findvideos', video_id=it['guid'])) return itemlist -def play(item): +def findvideos(item): logger.debug() item.no_return=True # support.dbg() @@ -262,7 +262,7 @@ def play(item): else: item.manifest = 'hls' - return[item] + return support.server(item, itemlist=[item], Download=False, Videolibrary=False) elif item.video_id: payload = '{"contentId":"' + item.video_id + ' ","streamType":"VOD","delivery":"Streaming","createDevice":true}' @@ -288,7 +288,7 @@ def play(item): else: item.manifest = 'hls' - return [item] + return support.server(item, itemlist=[item], Download=False, Videolibrary=False) def get_from_id(item): diff --git a/channels/metalvideo.py b/channels/metalvideo.py index 50c5817c..4623a086 100644 --- a/channels/metalvideo.py +++ b/channels/metalvideo.py @@ -41,6 +41,10 @@ def peliculas(item): patron= r'<img src="[^"]+" alt="(?P<title>[^"]+)" data-echo="(?P<thumb>[^"]+)"(?:[^>]+>){7}<a href="(?P<url>[^"]+)"' patronNext = r'<a href="([^"]+)">(?:»|»)' typeContentDict = {'': 'music'} + def itemHook(item): + item.contentType = 'music' + item.thumbnail = item.thumbnail.replace('https:','http:') + return item return locals() diff --git a/channels/netfreex.json b/channels/netfreex.json deleted file mode 100644 index 999eb078..00000000 --- a/channels/netfreex.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "netfreex", - "name": "Netfreex", - "language": ["ita"], - "active": false, - "thumbnail": "netfreex.png", - "banner": "netfreex.png", - "categories": ["tvshow", "movie", "anime"], - "not_active": ["include_in_newest_peliculas", "include_in_newest_anime", "include_in_newest_series"], - "settings": [] -} diff --git a/channels/netfreex.py b/channels/netfreex.py deleted file mode 100644 index 442145e7..00000000 --- a/channels/netfreex.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per netfreex -# ------------------------------------------------------------ - -from core import support -from core.item import Item -from platformcode import logger, config - -# def findhost(url): -# return 'https://' + support.match('https://netfreex.uno/', patron='value="site:([^"]+)"').match - -host = config.get_channel_url() -headers = "" - -IDIOMAS = {'Italiano': 'IT'} -list_language = IDIOMAS.values() - - -@support.menu -def mainlist(item): - - film = ['/film', - ('Generi', ['', 'menu', 'genres']) - ] - tvshow = ['/serietv'] - anime = ['/genere/anime'] - return locals() - - -def search(item, text): - logger.info('search', text) - item.url = item.url + "/?s=" + text - try: - return support.dooplay_search(item) - except: - import sys - for line in sys.exc_info(): - logger.error("%s" % line) - return [] - - -def peliculas(item): - if 'anime' in item.url: - return support.dooplay_peliculas(item, True) - else: - return support.dooplay_peliculas(item, False) - - -def episodios(item): - return support.dooplay_get_episodes(item) - - -def findvideos(item): - from core import jsontools - itemlist = [] - matches = support.match(item, patron=r'<li id="player-option-[0-9]".*?data-type="([^"]+)" data-post="([^"]+)" data-nume="([^"]+)".*?<span class="title".*?>([^<>]+)</span>(?:<span class="server">([^<>]+))?').matches - for Type, Post, Nume, Quality, Server in matches: - dataAdmin = support.match(host + '/wp-json/dooplayer/v1/post/%s?type=%s&source=%s' %(Post, Type, Nume)).data - js = jsontools.load(dataAdmin) - link = js['embed_url'] if 'embed_url' in js else '' - itemlist.append( item.clone(server=Server, quality=Quality, url=link, action='play')) - return support.server(item, itemlist=itemlist) - - -@support.scrape -def menu(item): - action = 'peliculas' - data = support.match(item, patron=r'<a href="#">Genere<(.*?)</ul').match - patronMenu= r'<a href="(?P<url>[^"]+)"[^>]*>(?P<title>[^<]+)<' - return locals() diff --git a/channels/paramount.py b/channels/paramount.py index 1049a1d0..a4259d61 100644 --- a/channels/paramount.py +++ b/channels/paramount.py @@ -7,6 +7,8 @@ from core import support, jsontools from platformcode import autorenumber, logger from collections import OrderedDict +from specials import videolibrary + host = support.config.get_channel_url() headers = [['Referer', host]] @@ -64,7 +66,7 @@ def live(item): logger.debug() 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)) + itemlist.append(item.clone(title=support.typo(key,'bold'), contentTitle=key, fulltitle=key, show=key, url=value['url'], plot=value['plot'], action='findvideos', forcethumb=True, no_return=True)) return support.thumb(itemlist, live=True) @@ -160,19 +162,22 @@ def episodios(item): def findvideos(item): logger.debug() - return support.server(item, itemlist=[item.clone(title='Paramount', server='directo', action='play')], Download=False) - - -def play(item): logger.debug() item.manifest = 'hls' mgid = support.match(item.url, patron=r'uri":"([^"]+)"').match url = 'https://media.mtvnservices.com/pmt/e1/access/index.html?uri=' + mgid + '&configtype=edge&ref=' + item.url ID, rootUrl = support.match(url, patron=[r'"id":"([^"]+)",',r'brightcove_mediagenRootURL":"([^"]+)"']).matches item.url = jsontools.load(support.match(rootUrl.replace('&device={device}','').format(uri = ID)).data)['package']['video']['item'][0]['rendition'][0]['src'] + return support.server(item, itemlist=[item.clone(title='Paramount', server='directo', action='play')], Download=False, Videolibrary=False) - 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) - return [item] \ No newline at end of file + +# def play(item): +# logger.debug() +# item.manifest = 'hls' +# mgid = support.match(item.url, patron=r'uri":"([^"]+)"').match +# url = 'https://media.mtvnservices.com/pmt/e1/access/index.html?uri=' + mgid + '&configtype=edge&ref=' + item.url +# ID, rootUrl = support.match(url, patron=[r'"id":"([^"]+)",',r'brightcove_mediagenRootURL":"([^"]+)"']).matches +# item.url = jsontools.load(support.match(rootUrl.replace('&device={device}','').format(uri = ID)).data)['package']['video']['item'][0]['rendition'][0]['src'] + + +# return [item] \ No newline at end of file diff --git a/channels/plutotv.py b/channels/plutotv.py index 23288a93..46fb9e9a 100644 --- a/channels/plutotv.py +++ b/channels/plutotv.py @@ -45,7 +45,7 @@ def live(item): itemlist.append(item.clone(title= '[B]{}[/B] | {}'.format(it['name'], guide[it['number']][0]), number=it['number'], contentTitle=it['name'], - action='play', + action='findvideos', thumbnail=it['solidLogoPNG']['path'], fanart=it['featuredImage']['path'], plot='{}\n\n[B]A seguire:[/B]\n{}'.format(it['summary'], guide[it['number']][1]), @@ -84,12 +84,11 @@ def peliculas(item): contentSerieName= it['name'] if it['type'] == 'series' else '', plot=it['description'], contentType='tvshow' if it['type'] == 'series' else 'movie', - action='episodios' if it['type'] == 'series' else 'play', + action='episodios' if it['type'] == 'series' else 'findvideos', thumbnail= it['covers'][0]['url'], fanart= it['covers'][2]['url'] if len(it['covers']) > 2 else '', id= it['_id'], - videourl= it['stitched']['urls'][0]['url'].split('?')[0], - forcethumb=True) + videourl= it['stitched']['urls'][0]['url'].split('?')[0]) if i < 20 or item.search: itemlist.append(itm) @@ -115,8 +114,7 @@ def episodios(item): plot=episode['description'], thumbnail=episode['covers'][1]['url'], videourl=episode['stitched']['urls'][0]['url'].split('?')[0], - action='play', - forcethumb=True)) + action='findvideos')) if config.get_setting('episode_info'): support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) @@ -124,7 +122,7 @@ def episodios(item): return itemlist -def play(item): +def findvideos(item): item.server = 'directo' item.manifest='hls' params = '{}?deviceDNT=0&deviceVersion=unknow&appVersion=unknow&deviceType=web&deviceMake=firefox&deviceModel=firefox&appName=web&{}' diff --git a/channels/polpotv.json b/channels/polpotv.json deleted file mode 100644 index 467bcffb..00000000 --- a/channels/polpotv.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": "polpotv", - "name": "PolpoTV", - "language": ["ita"], - "active": false, - "thumbnail": "polpotv.png", - "banner": "polpotv.png", - "categories": ["movie","tvshow"], - "not_active":[], - "default_off":["include_in_newest"], - "settings": [] -} \ No newline at end of file diff --git a/channels/polpotv.py b/channels/polpotv.py deleted file mode 100644 index 6d1fbae5..00000000 --- a/channels/polpotv.py +++ /dev/null @@ -1,227 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# KoD - XBMC Plugin -# Canale polpotv -# ------------------------------------------------------------ - -from core import support, jsontools -from core.item import Item -from platformcode import config -import datetime - -host = config.get_channel_url() - -headers = [['Accept', 'application/ld+json']] - - -@support.menu -def mainlist(item): - # menu = [ - # ('Ultimi Film aggiunti', ['/api/movies', 'peliculas', '']), - # ('Ultime Serie TV aggiunte', ['/api/shows', 'peliculas', '']), - # ('Generi', ['/api/genres', 'search_movie_by_genre', '']), - # ('Anni {film}', ['', 'search_movie_by_year', '']), - # ('Cerca... bold', ['', 'search', '']) - # ] - film = ['/api/movies', - ('Generi', ['/api/genres', 'search_movie_by_genre', '']), - ('Anni', ['', 'search_movie_by_year', '']),] - - tvshow=['/api/shows'] - - search='' - - return locals() - -def newest(categoria): - support.info() - item = Item() - if categoria == 'peliculas': - item.contentType = 'movie' - item.url = host + '/api/movies' - elif categoria == 'series': - item.contentType = 'tvshow' - item.url = host+'/api/shows' - return peliculas(item) - -def peliculas(item): - support.info() - itemlist = [] - - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - for element in json_object['hydra:member']: - if 'shows' not in item.url: - item.contentType='movie' - else: - item.contentType='tvshow' - itemlist.append(get_itemlist_element(element, item)) - - support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - try: - if support.inspect.stack()[1][3] not in ['newest']: - support.nextPage(itemlist, item, next_page=json_object['hydra:view']['hydra:next']) - except: - pass - - return itemlist - -def episodios(item): - support.info() - itemlist = [] - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - for season in json_object['seasons']: - seas_url=host+season['@id']+'/releases' - itemlist_season=get_season(item, seas_url, season['seasonNumber']) - if(len(itemlist_season)>0): - itemlist.extend(itemlist_season) - - support.videolibrary(itemlist, item, 'color kod bold') - support.download(itemlist, item) - - return itemlist - -def get_season(item, seas_url, seasonNumber): - support.info() - itemlist = [] - data = support.match(seas_url, headers=headers).data - json_object = jsontools.load(data) - for episode in json_object['hydra:member']: - itemlist.append( - item.clone(action='findvideos', - contentType='episode', - title=support.typo(str(seasonNumber)+"x"+str("%02d"%episode['episodeNumber']), 'bold'), - url=seas_url, - extra=str(len(json_object['hydra:member'])-episode['episodeNumber']))) - return itemlist[::-1] - -def search(item, texto): - support.info(item.url, "search", texto) - itemlist=[] - try: - item.url = host + "/api/movies?originalTitle="+texto+"&translations.name=" +texto - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - for movie in json_object['hydra:member']: - item.contentType='movie' - itemlist.append(get_itemlist_element(movie,item)) - item.url = host + "/api/shows?originalTitle="+texto+"&translations.name=" +texto - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - for tvshow in json_object['hydra:member']: - item.contentType='tvshow' - itemlist.append(get_itemlist_element(tvshow,item)) - support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - return itemlist - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.logger.error("%s" % line) - return [] - - -def search_movie_by_genre(item): - support.info() - itemlist = [] - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - for genre in json_object['hydra:member']: - itemlist.append( - item.clone(action="peliculas", - title=support.typo(genre['name'],'bold'), - contentType='movie', - url="%s/api/movies?genres.id=%s" %(host,genre['id']))) - return support.thumb(itemlist, True) - - -def search_movie_by_year(item): - support.info() - now = datetime.datetime.now() - year = int(now.year) - itemlist = [] - for i in range(100): - year_to_search = year - i - itemlist.append( - item.clone(channel=item.channel,url="%s/api/movies?releaseDate=%s" %(host,year_to_search), - plot="1", - type="movie", - title=support.typo(year_to_search,'bold'), - action="peliculas")) - return itemlist - - -def findvideos(item): - support.info() - itemlist = [] - try: - data = support.match(item.url, headers=headers).data - json_object = jsontools.load(data) - array_index=0 - if item.contentType!='movie': - array_index=int(item.extra) - for video in json_object['hydra:member'][array_index]['playlist']['videos']: - itemlist.append( - item.clone(action="play", - title='Direct', - url=video['src'], - server='directo', - quality=str(video['size'])+ 'p', - folder=False)) - except: - pass - return support.server(item, itemlist=itemlist) - - -def get_itemlist_element(element,item): - support.info() - contentSerieName = '' - contentTitle ='' - try: - if element['originalLanguage']['id']=='it': - scrapedtitle=element['originalTitle'] - else: - scrapedtitle=element['translations'][1]['name'] - if scrapedtitle=='': - scrapedtitle=element['originalTitle'] - except: - scrapedtitle=element['originalTitle'] - try: - scrapedplot=element['translations'][1]['overview'] - except: - scrapedplot = "" - try: - scrapedthumbnail="https:"+element['bestPosters'].values()[0] - except: - scrapedthumbnail="" - # try: - # scrapedfanart="http:"+element['backdropPath'] - # except: - # scrapedfanart="" - - infoLabels = {} - if item.contentType=='movie': - contentTitle = scrapedtitle - next_action='findvideos' - quality=support.typo(element['lastQuality'].upper(), '_ [] color kod bold') - url="%s%s/releases" - infoLabels['tmdb_id']=element['tmdbId'] - else: - contentSerieName = scrapedtitle - next_action='episodios' - quality='' - url="%s%s" - - return item.clone(action=next_action, - title=support.typo(scrapedtitle, 'bold') + quality, - fulltitle=scrapedtitle, - show=scrapedtitle, - plot=scrapedplot, - # fanart=scrapedfanart, - thumbnail=scrapedthumbnail, - contentTitle=contentTitle, - contentSerieName=contentSerieName, - contentType=item.contentType, - url=url % (host, element['@id']), - infoLabels=infoLabels) diff --git a/channels/pufimovies.json b/channels/pufimovies.json deleted file mode 100644 index 64b72651..00000000 --- a/channels/pufimovies.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "pufimovies", - "name": "PufiMovies", - "active": false, - "language": ["ita", "sub-ita"], - "thumbnail": "pufimovies.png", - "banner": "pufimovies.png", - "categories": ["movie","tvshow"], - "settings": [] -} diff --git a/channels/pufimovies.py b/channels/pufimovies.py deleted file mode 100644 index 4795a360..00000000 --- a/channels/pufimovies.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per PufiMovies -# ------------------------------------------------------------ - -from core import support - -host = support.config.get_channel_url() - - - - -headers = [['Referer', host]] - - -@support.menu -def mainlist(item): - film = [ - ('Generi', ['', 'menu', 'Film']), - ('Più Visti', ['','peliculas', 'most']) - ] - - tvshow = ['', - ('Generi', ['', 'menu', 'Serie Tv']), - ('Ultimi Episodi', ['','peliculas', 'last']) - ] - - search = '' - return locals() - - -@support.scrape -def menu(item): - action = 'peliculas' - patronBlock = item.args + r' Categorie</a>\s*<ul(?P<block>.*?)</ul>' - patronMenu = r'<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^>]+)<' - return locals() - - -def search(item, text): - support.info('search', item) - itemlist = [] - text = text.replace(' ', '+') - item.url = host + '/search/keyword/' + text - try: - item.args = 'search' - itemlist = peliculas(item) - if itemlist[-1].action == 'peliculas': - itemlist.pop() - return itemlist - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.info('search log:', line) - return [] - - -def newest(categoria): - support.info(categoria) - itemlist = [] - item = support.Item() - item.url = host - item.action = 'peliculas' - try: - if categoria == 'peliculas': - item.contentType = 'movie' - itemlist = peliculas(item) - else: - item.args = 'last' - item.contentType = 'tvshow' - itemlist = peliculas(item) - - if itemlist[-1].action == 'peliculas': - itemlist.pop() - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.logger.error("%s" % line) - return [] - - return itemlist - - -@support.scrape -def peliculas(item): - if item.contentType == 'tvshow' and not item.args: - action = 'episodios' - patron = r'<div class="movie-box">\s*<a href="(?P<url>[^"]+)">[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)[^>]+>[^>]+>[^>]+>(?P<quality>[^<]+)[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?P<year>\d+)' - elif item.contentType == 'movie' and not item.args: - patron = r'<div class="existing_item col-6 col-lg-3 col-sm-4 col-xl-4">\s*<div class="movie-box">\s*<a href="(?P<url>(?:http(?:s)://[^/]+)?/(?P<type>[^/]+)/[^"]+)">[^>]+>[^>]+>\D+Streaming\s*(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?:(?P<year>\d+))?[^>]+>[^>]+>[^>]+>[^>]+>(?P<plot>[^<]*)<' - elif item.args == 'last': - patron = r'<div class="episode-box">[^>]+>[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>[^^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>[^<]+)<[^>]+>[^>]+>[^>]+>\D*(?P<season>\d+)[^>]+>\D*(?P<episode>\d+)' - elif item.args == 'most': - patron =r'div class="sm-113 item">\s*<a href="(?P<url>[^"]+)">[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*(?P<title>[^<]+)' - else: - patron = r'<div class="movie-box">\s*<a href="(?P<url>(?:http(?:s)://[^/]+)?/(?P<type>[^/]+)/[^"]+)">[^>]+>[^>]+>\D+Streaming\s*(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?:(?P<year>\d+))?[^>]+>[^>]+>[^>]+>[^>]+>(?P<plot>[^<]*)<' - typeActionDict = {'findvideos':['movie'], 'episodios':['tvshow']} - typeContentDict = {'movie':['movie'], 'tvshow':['tvshow']} - patronNext = r'<a href="([^"]+)"[^>]+>»' - return locals() - - -@support.scrape -def episodios(item): - patron = r'<div class="episode-box">[^>]+>[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>[^<]+)<[^>]+>[^>]+>[^>]+>\D*(?P<season>\d+)[^>]+>\D*(?P<episode>\d+)' - return locals() - - -def findvideos(item): - support.info() - # match = support.match(item, patron='wstream', debug=True) - return support.server(item) diff --git a/channels/raiplay.py b/channels/raiplay.py index 3b968d76..54ff89a7 100644 --- a/channels/raiplay.py +++ b/channels/raiplay.py @@ -142,7 +142,7 @@ def live(item): 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.append(item.clone(title=title, fulltitle=title, fanart=fanart, plot=plot, url=url, video_url=url + '.json', action='findvideos')) itemlist.sort(key=lambda it: support.channels_order.get(it.fulltitle, 999)) support.thumb(itemlist, live=True) return itemlist @@ -209,7 +209,7 @@ def replay(item): plot = info['description'], url = getUrl(it['weblink']), video_url = getUrl(it['path_id']), - action = 'play', + action = 'findvideos', forcethumb = True) @@ -229,7 +229,7 @@ def replay(item): return itemlist -def play(item): +def findvideos(item): logger.debug() res = requests.get(item.video_url).json() @@ -245,7 +245,7 @@ def play(item): item = item.clone(server='directo', url=url, no_return=True) # , manifest='hls') - return [item] + return support.server(item, itemlist=[item], Download=False, Videolibrary=False) def getUrl(url): @@ -306,7 +306,7 @@ def addinfo(items, item): order=n) if 'Genere' not in key.get('sub_type', '') and ('layout' not in key or key['layout'] == 'single'): - it.action = 'play' + it.action = 'findvideos' it.contentTitle = it.fulltitle else: it.action = 'episodios' diff --git a/channels/seriehd.json b/channels/seriehd.json deleted file mode 100644 index 9c7ade33..00000000 --- a/channels/seriehd.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "seriehd", - "name": "SerieHD", - "active": false, - "language": ["ita"], - "thumbnail": "seriehd.png", - "banner": "seriehd.png", - "categories": ["tvshow"], - "settings": [], - "cloudflare": true -} diff --git a/channels/seriehd.py b/channels/seriehd.py deleted file mode 100644 index 8aba8a60..00000000 --- a/channels/seriehd.py +++ /dev/null @@ -1,156 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per SerieHD -# ------------------------------------------------------------ - - -from core import support -def findhost(url): - return support.match(url, patron=r'<h2[^>]+><a href="([^"]+)"').match - -host = support.config.get_channel_url() -headers = [['Referer', host]] - - -@support.menu -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']), - ('Ultimi Episodi', ['/aggiornamenti', 'peliculas', 'last']), - ('Evidenza', ['', 'peliculas', 'best'])] - return locals() - - -def search(item, texto): - support.info(texto) - - - item.contentType = 'tvshow' - item.url = host + "/?s=" + texto - try: - 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 newest(categoria): - support.info(categoria) - - itemlist = [] - item = support.Item() - item.url = host + '/aggiornamenti' - item.args = 'last' - try: - if categoria == "series": - item.contentType = 'tvshow' - return peliculas(item) - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.logger.error("{0}".format(line)) - return [] - - return itemlist - - -@support.scrape -def peliculas(item): - # debug = True - - if item.args == 'last': - action = 'findvideos' - patron = r'singleUpdate">(?:[^>]+>){2}\s*<img src="(?P<thumb>[^"]+)"(?:[^>]+>){3}\s*<h2>(?P<title>[^<]+)<(?:[^>]+>){14,16}\s*<a href="(?P<url>[^"]+)">(?:[^>]+>){3}\s*(?P<season>\d+)\D+(?P<episode>\d+)(?:[^\(]*\()?(?P<lang>[^\)]+)?(?:\))?' - elif item.args == 'best': - action='episodios' - patron = r'col-md-3">\s*<a href="(?P<url>[^"]+)">[^>]+>\s*<div class="infoVetrina">[^>]+>(?P<year>\d{4})(?:[^>]+>){2}(?P<title>[^<]+)<(?:[^>]+>){4}(?P<rating>[^<]+)(?:[^>]+>){4}\s*<img src="(?P<thumb>[^"]+)"' - else: - action='episodios' - # patron = r'<a href="(?P<url>[^"]+)">[^>]+>\s*<div class="infoSeries">\s*<h2>(?P<title>[^<]+)<(?:[^>]+>){5}(?P<rating>[^<]+)?(?:[^>]+>){3}\s*<img src="(?P<thumb>[^"]+)"(?:[^>]+>){3}(?P<quality>[^<]+)<(?:[^>]+>){2}(?P<year>\d{4})' - patron = r'<a href="(?P<url>[^"]+)">[^>]+>\s*<div class="infoSeries">\s*<h2>(?P<title>[^<]+?)(?:\[(?P<lang>[^\]]+)\])?<(?:[^>]+>){5}(?P<rating>[^<]+)?(?:[^>]+>){3}\s*(?:<img src="(?P<thumb>[^"]+)"[^>]+>)?(?:[^>]+>){0,2}(?P<quality>[^<]+)<(?:[^>]+>){2}(?P<year>\d{4})' - patronNext=r'next page-numbers" href="([^"]+)"' - - return locals() - - -@support.scrape -def episodios(item): - def get_season(pageData, seas_url, season): - data = '' - episodes = support.match(pageData if pageData else seas_url, patronBlock=patron_episode, patron=patron_option).matches - for episode_url, episode in episodes: - # episode_url = support.urlparse.urljoin(item.url, episode_url) - # if '-' in episode: episode = episode.split('-')[0].zfill(2) + 'x' + episode.split('-')[1].zfill(2) - title = season + "x" + episode.zfill(2) + ' - ' + item.fulltitle - data += title + '|' + episode_url + '\n' - return data - - patron_season = '<div class="[^"]+" id="seasonsModal"[^>]+>(.*?)</ul>' - patron_episode = '<div class="[^"]+" id="episodesModal"[^>]+>(.*?)</ul>' - patron_option = r'<a href="([^"]+?)".*?>(?:Stagione |Episodio )([^<]+?)</a>' - - url = support.match(item, patron=r'<iframe id="iframeVid" width="[^"]+" height="[^"]+" src="([^"]+)" allowfullscreen').match - seasons = support.match(url, patronBlock=patron_season, patron=patron_option) - - data = '' - - # debugging - # support.dbg() - # for i, season in enumerate(seasons.matches): - # data += get_season(seasons.data if i == 0 else '', season[0], season[1]) - import sys - if sys.version_info[0] >= 3: from concurrent import futures - else: from concurrent_py2 import futures - with futures.ThreadPoolExecutor() as executor: - thL = [] - for i, season in enumerate(seasons.matches): - thL.append(executor.submit(get_season, seasons.data if i == 0 else '', season[0], season[1])) - for res in futures.as_completed(thL): - if res.result(): - data += res.result() - # debug = True - patron = r'(?P<season>\d+)x(?P<episode>\d+)\s*-\s*(?P<title>[^\|]+)\|(?P<url>[^ ]+)' - action = 'findvideos' - - def itemlistHook(itemlist): - itemlist.sort(key=lambda item: (item.infoLabels['season'], item.infoLabels['episode'])) - return itemlist - - return locals() - - -@support.scrape -def menu(item): - if item.args == 'genre': - patronMenu = r'<a href="(?P<url>[^"]+)">(?P<title>[^<]+)</a>' - else: - patronMenu = r'<a href="(?P<url>[^"]+)" class="">(?P<title>[^<]+)' - - blacklist = ['Serie TV Streaming','Serie TV Americane','Serie TV Italiane','Serie Complete','Serie in Corso','altadefinizione'] - action = 'peliculas' - return locals() - - -def findvideos(item): - item.url = item.url.replace('&', '&') - support.info(item) - if item.args == 'last': - url = support.match(item, patron = r'<iframe id="iframeVid" width="[^"]+" height="[^"]+" src="([^"]+)" allowfullscreen').match - matches = support.match(url,patron=r'<a href="([^"]+)">(\d+)<', patronBlock=r'<h3>EPISODIO</h3><ul>(.*?)</ul>').matches - if matches: item.url = support.urlparse.urljoin(url, matches[-1][0]) - return support.hdpass_get_servers(item) - - -def play(item): - if 'hdpass' in item.url: - return support.hdpass_get_url(item) - return [item] \ No newline at end of file diff --git a/channels/serietvonline.json b/channels/serietvonline.json deleted file mode 100644 index 97164cd0..00000000 --- a/channels/serietvonline.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "serietvonline", - "name": "SerieTvOnline", - "active": false, - "language": ["ita"], - "thumbnail": "serietvonline.png", - "bannermenu": "serietvonline.png", - "categories": ["anime","tvshow","movie","documentary"], - "not_active": ["include_in_newest_anime"], - "settings": [] -} diff --git a/channels/serietvonline.py b/channels/serietvonline.py deleted file mode 100644 index b2b1e45b..00000000 --- a/channels/serietvonline.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per serietvonline.py -# ---------------------------------------------------------- -""" - Novità. Indicare in quale/i sezione/i è presente il canale: - - film, serie - - Avvisi: - - Al massimo 25 titoli per le sezioni: Film - - Al massimo 35 titoli per le sezioni: Tutte le altre - Per aggiungere in videoteca le Anime: - Se hanno la forma 1x01: - -si posso aggiungere direttamente dalla pagina della serie, sulla voce in fondo "aggiungi in videoteca". - Altrimenti: - - Prima fare la 'Rinumerazione' dal menu contestuale dal titolo della serie -""" -import re -from core import support, httptools, scrapertools -from platformcode import config -from core.item import Item - - -# def findhost(url): -# host = support.match(url, patron=r'href="([^"]+)">\s*cliccando qui').matches[-1] -# return host - -host = config.get_channel_url() -headers = [['Referer', host]] - - -@support.menu -def mainlist(item): - support.info() - - - film = ['/ultimi-film-aggiunti/', - ('A-Z', ['/lista-film/', 'peliculas', 'lista']) - ] - - tvshow = ['', - ('Aggiornamenti', ['/ultimi-episodi-aggiunti/', 'peliculas', 'update']), - ('Tutte', ['/lista-serie-tv/', 'peliculas', 'qualcosa']), - ('Italiane', ['/lista-serie-tv-italiane/', 'peliculas', 'qualcosa']), - ('Anni 50-60-70-80', ['/lista-serie-tv-anni-60-70-80/', 'peliculas', 'qualcosa']), - ('HD', ['/lista-serie-tv-in-altadefinizione/', 'peliculas', 'qualcosa']) - ] - - anime = ['/lista-cartoni-animati-e-anime/'] - - documentari = [('Documentari {bullet bold}', ['/lista-documentari/' , 'peliculas' , 'doc', 'tvshow'])] - - search = '' - - return locals() - -@support.scrape -def peliculas(item): - support.info() - anime = True - - blacklist = ['DMCA', 'Contatti', 'Attenzione NON FARTI OSCURARE', 'Lista Cartoni Animati e Anime'] - patronBlock = r'<h1>.+?</h1>(?P<block>.*?)<div class="footer_c">' - patronNext = r'<div class="siguiente"><a href="([^"]+)" >' - # debug = True - - if item.args == 'search': - patronBlock = r'>Lista Serie Tv</a></li></ul></div><div id="box_movies">(?P<block>.*?)<div id="paginador">' - patron = r'<div class="movie">[^>]+[^>]+>\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.+?)(?:(?P<year>\d{4})|")[^>]*>\s*<a href="(?P<url>[^"]+)' - elif item.contentType == 'episode': - pagination = 35 - action = 'findvideos' - patron = r'<td><a href="(?P<url>[^"]+)"(?:[^>]+)?>\s?(?P<title>.*?)(?P<episode>\d+x\d+)[ ]?(?P<title2>[^<]+)?<' - - elif item.contentType == 'tvshow': - # SEZIONE Serie TV- Anime - Documentari - pagination = 35 - - if not item.args and 'anime' not in item.url: - patron = r'<div class="movie">[^>]+>.+?src="(?P<thumb>[^"]+)" alt="[^"]+".+? href="(?P<url>[^"]+)">.*?<h2>(?P<title>[^"]+)</h2>\s?(?:<span class="year">(?P<year>\d+|\-\d+))?<' - else: - anime = True - patron = r'(?:<td>)?<a href="(?P<url>[^"]+)"(?:[^>]+)?>\s?(?P<title>[^<]+)(?P<episode>[\d\-x]+)?(?P<title2>[^<]+)?<' - else: - # SEZIONE FILM - pagination = 25 - - if item.args == 'lista': - patron = r'href="(?P<url>[^"]+)"[^>]+>(?P<title>.+?)(?:\s(?P<year>\d{4})|<)' - patronBlock = r'Lista dei film disponibili in streaming e anche in download\.</p>(?P<block>.*?)<div class="footer_c">' - else: - patron = r'<tr><td><a href="(?P<url>[^"]+)"(?:|.+?)?>(?:  )?[ ]?(?P<title>.*?)[ ]?(?P<quality>HD)?[ ]?(?P<year>\d+)?(?: | HD[^<]*| Streaming[^<]*| MD(?: iSTANCE)? [^<]*)?</a>' - - def itemHook(item): - if 'film' in item.url: - item.action = 'findvideos' - item.contentType = 'movie' - elif item.args == 'update': - pass - else: - item.contentType = 'tvshow' - item.action = 'episodios' - return item - return locals() - - -@support.scrape -def episodios(item): - support.info() - anime = True - action = 'findvideos' - patronBlock = r'<table>(?P<block>.*)<\/table>' - patron = r'<tr><td>(?P<title>.*?)?[ ](?:Parte)?(?P<episode>\d+x\d+|\d+)(?:|[ ]?(?P<title2>.+?)?(?:avi)?)<(?P<data>.*?)<\/td><tr>' - def itemlistHook(itemlist): - for i, item in enumerate(itemlist): - ep = support.match(item.title, patron=r'\d+x(\d+)').match - if ep == '00': - item.title = item.title.replace('x00', 'x' + str(i+1).zfill(2)).replace('- ..','') - return itemlist - return locals() - - -def search(item, text): - support.info("CERCA :" ,text, item) - - item.url = "%s/?s=%s" % (host, text) - - try: - item.args = 'search' - return peliculas(item) - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.info("%s" % line) - return [] - -def newest(categoria): - support.info(categoria) - - itemlist = [] - item = Item() - - if categoria == 'peliculas': - item.contentType = 'movie' - item.url = host + '/ultimi-film-aggiunti/' - elif categoria == 'series': - item.args = 'update' - item.contentType = 'episode' - item.url = host +'/ultimi-episodi-aggiunti/' - try: - item.action = 'peliculas' - itemlist = peliculas(item) - - except: - import sys - for line in sys.exc_info(): - support.info("{0}".format(line)) - return [] - - return itemlist - -def findvideos(item): - support.info() - if item.contentType == 'movie': - return support.server(item, headers=headers) - else: - - if item.args != 'update': - return support.server(item, item.data) - else: - itemlist = [] - item.infoLabels['mediatype'] = 'episode' - - data = support.match(item.url, headers=headers).data - url_video = scrapertools.find_single_match(data, r'<tr><td>(.+?)</td><tr>', -1) - url_serie = scrapertools.find_single_match(data, r'<link rel="canonical" href="([^"]+)"\s?/>') - goseries = support.typo("Vai alla Serie:", ' bold') - series = support.typo(item.contentSerieName, ' bold color kod') - itemlist = support.server(item, data=url_video) - - itemlist.append(item.clone(title=goseries + series, contentType='tvshow', url=url_serie, action='episodios', plot = goseries + series + "con tutte le puntate", args='')) - - return itemlist diff --git a/channels/serietvsubita.json b/channels/serietvsubita.json deleted file mode 100644 index 2cd33c2f..00000000 --- a/channels/serietvsubita.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "id": "serietvsubita", - "name": "Serie TV Sub ITA", - "active": false, - "language": ["ita"], - "thumbnail": "serietvsubita.png", - "banner": "serietvsubita.png", - "categories": ["tvshow"], - "settings": [ - { - "id": "include_in_global_search", - "type": "bool", - "label": "Includi ricerca globale", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "include_in_newest_series", - "type": "bool", - "label": "Includi in Novità - Serie TV", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "checklinks", - "type": "bool", - "label": "Verifica se i link esistono", - "default": false, - "enabled": true, - "visible": true - }, - { - "id": "checklinks_number", - "type": "list", - "label": "Numero de link da verificare", - "default": 1, - "enabled": true, - "visible": "eq(-1,true)", - "lvalues": [ "1", "3", "5", "10" ] - }, - { - "id": "filter_languages", - "type": "list", - "label": "Mostra link in lingua...", - "default": 0, - "enabled": true, - "visible": true, - "lvalues": ["Non filtrare","IT"] - } - ] -} diff --git a/channels/serietvsubita.py b/channels/serietvsubita.py deleted file mode 100644 index 80a99a45..00000000 --- a/channels/serietvsubita.py +++ /dev/null @@ -1,351 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per Serietvsubita -# Thanks to Icarus crew & Alfa addon & 4l3x87 -# ---------------------------------------------------------- - -import re -import time - -from core import httptools, tmdb, scrapertools, support -from core.item import Item -from core.support import info -from platformcode import logger, config - -host = config.get_channel_url() -headers = [['Referer', host]] - -IDIOMAS = {'Italiano': 'IT'} -list_language = IDIOMAS.values() - - -@support.menu -def mainlist(item): - info() - itemlist = [] - tvshowSub = [ - ('Novità {bold}',[ '', 'peliculas_tv', '', 'tvshow']), - ('Serie TV {bold}',[ '', 'lista_serie', '', 'tvshow']), - ('Per Lettera', ['', 'list_az', 'serie', 'tvshow']) - ] - cerca = [(support.typo('Cerca...', 'bold'),[ '', 'search', '', 'tvshow'])] -## support.aplay(item, itemlist, list_servers, list_quality) -## support.channel_config(item, itemlist) - - return locals() - - - -# ---------------------------------------------------------------------------------------------------------------- -def cleantitle(scrapedtitle): - scrapedtitle = scrapertools.decodeHtmlentities(scrapedtitle.strip()) - scrapedtitle = scrapedtitle.replace('[HD]', '').replace('’', '\'').replace('×', 'x').replace('Game of Thrones –','')\ - .replace('In The Dark 2019', 'In The Dark (2019)').replace('"', "'").strip() - year = scrapertools.find_single_match(scrapedtitle, r'\((\d{4})\)') - if year: - scrapedtitle = scrapedtitle.replace('(' + year + ')', '') - - return scrapedtitle.strip() - - -# ================================================================================================================ - -# ---------------------------------------------------------------------------------------------------------------- -def findvideos(item): - info() - data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data - data = re.sub(r'\n|\t|\s+', ' ', data) - # recupero il blocco contenente i link - blocco = scrapertools.find_single_match(data, r'<div class="entry">([\s\S.]*?)<div class="post').replace('..:: Episodio ', 'Episodio ').strip() - matches = scrapertools.find_multiple_matches(blocco, r'(S(\d*)E(\d*))\s') - if len(matches) > 0: - for fullseasonepisode, season, episode in matches: - blocco = blocco.replace(fullseasonepisode + ' ', 'Episodio ' + episode + ' ') - - blocco = blocco.replace('Episodio ', '..:: Episodio ') - - episodio = item.infoLabels['episode'] - patron = r'\.\.:: Episodio %s([\s\S]*?)(<div class="post|..:: Episodio)' % episodio - info(patron) - info(blocco) - - matches = scrapertools.find_multiple_matches(blocco, patron) - if len(matches): - data = matches[0][0] - - patron = r'href="(https?://www\.keeplinks\.(?:co|eu)/p(?:[0-9]*)/([^"]+))"' - matches = re.compile(patron, re.DOTALL).findall(data) - for keeplinks, id in matches: - headers2 = [['Cookie', 'flag[' + id + ']=1; defaults=1; nopopatall=' + str(int(time.time()))], - ['Referer', keeplinks]] - - html = httptools.downloadpage(keeplinks, headers=headers2).data - data += str(scrapertools.find_multiple_matches(html, '</lable><a href="([^"]+)" target="_blank"')) - - return support.server(item, data=data) - -# ================================================================================================================ - - -# ---------------------------------------------------------------------------------------------------------------- -def lista_serie(item): - info() - itemlist = [] - - PERPAGE = 15 - - p = 1 if not item.args else int(item.args) - - if '||' in item.data: - series = item.data.split('\n\n') - matches = [] - for i, serie in enumerate(series): - matches.append(serie.split('||')) - else: - # Extrae las entradas - patron = r'<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron=patron, headers=headers).matches - for i, (scrapedurl, scrapedtitle) in enumerate(matches): - scrapedplot = "" - scrapedthumbnail = "" - if (p - 1) * PERPAGE > i: continue - if i >= p * PERPAGE: break - title = cleantitle(scrapedtitle) - itemlist.append( - item.clone(action="episodios", - title=title, - url=scrapedurl, - thumbnail=scrapedthumbnail, - fulltitle=title, - show=title, - plot=scrapedplot, - contentType='episode', - originalUrl=scrapedurl)) - - tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - - # Paginazione - if len(matches) >= p * PERPAGE: - item.args = p + 1 - support.nextPage(itemlist, item, next_page=item.url) - - return itemlist - - -# ================================================================================================================ - - -# ---------------------------------------------------------------------------------------------------------------- -def episodios(item, itemlist=[]): - info() - patron = r'<div class="post-meta">\s*<a href="([^"]+)"\s*title="([^"]+)"\s*class=".*?"></a>.*?' - patron += r'<p><a href="([^"]+)">' - - - html = support.match(item, patron=patron, headers=headers) - matches = html.matches - data = html.data - - for scrapedurl, scrapedtitle, scrapedthumbnail in matches: - scrapedplot = "" - scrapedtitle = cleantitle(scrapedtitle) - if "(Completa)" in scrapedtitle: - data = httptools.downloadpage(scrapedurl, headers=headers).data - scrapedtitle = scrapedtitle.replace(" – Miniserie", " – Stagione 1") - title = scrapedtitle.split(" – Stagione")[0].strip() - - # recupero la stagione - season = scrapertools.find_single_match(scrapedtitle, 'Stagione ([0-9]*)') - blocco = scrapertools.find_single_match(data, r'<div class="entry">[\s\S.]*?<div class="post') - blocco = blocco.replace('<strong>Episodio ', '<strong>Episodio ').replace(' </strong>', ' </strong>') - blocco = blocco.replace('<strong>Episodio ', '<strong>S' + season.zfill(2) + 'E') - matches = scrapertools.find_multiple_matches(blocco, r'(S(\d*)E(\d*))\s') - episodes = [] - if len(matches) > 0: - for fullepisode_s, season, episode in matches: - season = season.lstrip("0") - - episodes.append([ - "".join([season, "x", episode]), - season, - episode - ]) - - else: - title = scrapedtitle.split(" S0")[0].strip() - title = title.split(" S1")[0].strip() - title = title.split(" S2")[0].strip() - episodes = scrapertools.find_multiple_matches(scrapedtitle, r'((\d*)x(\d*))') - - for fullepisode, season, episode in episodes: - infoLabels = {} - infoLabels['season'] = season - infoLabels['episode'] = episode - fullepisode += ' ' + support.typo("Sub-ITA", '_ [] color kod') - itemlist.append( - item.clone(action="findvideos", - fulltitle=scrapedtitle, - show=scrapedtitle, - title=fullepisode, - url=scrapedurl, - thumbnail=scrapedthumbnail, - plot=scrapedplot, - contentSerieName=title, - infoLabels=infoLabels)) - - tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - - # Paginazionazione - patron = r'<strong class="on">\d+</strong>\s*<a href="([^<]+)">\d+</a>' - next_page = scrapertools.find_single_match(data, patron) - if next_page != "": - item.url = next_page - itemlist = episodios(item, itemlist) - else: - item.url = item.originalUrl - support.videolibrary(itemlist, item, 'bold color kod') - - return itemlist - - -# ================================================================================================================ - -# ---------------------------------------------------------------------------------------------------------------- -def peliculas_tv(item): - info() - itemlist = [] - - patron = r'<div class="post-meta">\s*<a href="([^"]+)"\s*title="([^"]+)"\s*class=".*?"></a>' - - html = support.match(item, patron=patron, headers=headers) - matches = html.matches - data = html.data - - for scrapedurl, scrapedtitle in matches: - if scrapedtitle in ["FACEBOOK", "RAPIDGATOR", "WELCOME!"]: - continue - - scrapedthumbnail = "" - scrapedplot = "" - scrapedtitle = cleantitle(scrapedtitle) - infoLabels = {} - episode = scrapertools.find_multiple_matches(scrapedtitle, r'((\d*)x(\d*))') - if episode: # workaround per quando mettono le serie intere o altra roba, sarebbero da intercettare TODO - episode = episode[0] - title = scrapedtitle.split(" S0")[0].strip() - title = title.split(" S1")[0].strip() - title = title.split(" S2")[0].strip() - - infoLabels['season'] = episode[1] - infoLabels['episode'] = episode[2].zfill(2) - - itemlist.append( - item.clone(action="findvideos", - fulltitle=scrapedtitle, - show=scrapedtitle, - title=title + " - " + episode[0] + " " + support.typo("Sub-ITA", '_ [] color kod'), - url=scrapedurl, - thumbnail=scrapedthumbnail, - contentSerieName=title, - contentLanguage='Sub-ITA', - plot=scrapedplot, - infoLabels=infoLabels)) - - tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - - # Paginazione - patron = r'<strong class="on">\d+</strong>\s?<a href="([^<]+)">\d+</a>' - support.nextPage(itemlist, item, data, patron) - - return itemlist - - -# ================================================================================================================ - - -# ---------------------------------------------------------------------------------------------------------------- -def newest(categoria): - info(categoria) - itemlist = [] - item = Item() - item.url = host - item.extra = 'serie' - try: - if categoria == "series": - itemlist = peliculas_tv(item) - if itemlist[-1].action == 'peliculas_tv': - itemlist.pop(-1) - - except: - import sys - for line in sys.exc_info(): - logger.error("{0}".format(line)) - return [] - - return itemlist - - -# ================================================================================================================ - -# ---------------------------------------------------------------------------------------------------------------- -def search(item, texto): - info(texto) - itemlist = [] - try: - patron = r'<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron=patron, headers=headers).matches - for i, (scrapedurl, scrapedtitle) in enumerate(matches): - if texto.upper() in scrapedtitle.upper(): - scrapedthumbnail = "" - scrapedplot = "" - title = cleantitle(scrapedtitle) - itemlist.append( - item.clone(action="episodios", - title=title, - url=scrapedurl, - thumbnail=scrapedthumbnail, - fulltitle=title, - show=title, - plot=scrapedplot, - contentType='episode', - originalUrl=scrapedurl)) - tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - except: - import sys - for line in sys.exc_info(): - support.info('search log:', line) - return [] - - return itemlist - - -# ================================================================================================================ - -# ---------------------------------------------------------------------------------------------------------------- - - -def list_az(item): - info() - itemlist = [] - - alphabet = dict() - patron = r'<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron=patron, headers=headers).matches - for i, (scrapedurl, scrapedtitle) in enumerate(matches): - letter = scrapedtitle[0].upper() - if letter not in alphabet: - alphabet[letter] = [] - alphabet[letter].append(scrapedurl + '||' + scrapedtitle) - - for letter in sorted(alphabet): - itemlist.append( - item.clone(action="lista_serie", - data='\n\n'.join(alphabet[letter]), - title=letter, - fulltitle=letter, - args='')) - - return itemlist - -# ================================================================================================================ - diff --git a/channels/streamingaltadefinizione.json b/channels/streamingaltadefinizione.json deleted file mode 100644 index 404c2ddb..00000000 --- a/channels/streamingaltadefinizione.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "streamingaltadefinizione", - "name": "Popcorn Stream", - "language": ["ita"], - "active": false, - "thumbnail": "popcornstream.png", - "banner": "popcornstream.png", - "categories": ["movie","tvshow","anime"], - "not_active":["include_in_newest_peliculas", "include_in_newest_series", "include_in_newest_anime"], - "settings": [] -} diff --git a/channels/streamingaltadefinizione.py b/channels/streamingaltadefinizione.py deleted file mode 100644 index f0685434..00000000 --- a/channels/streamingaltadefinizione.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per Popcorn Stream -# ------------------------------------------------------------ - -from core import support, httptools -from core.item import Item -from platformcode import config -import sys -if sys.version_info[0] >= 3: - from urllib.parse import unquote -else: - from urllib import unquote - - -def findhost(url): - data = httptools.downloadpage(url).data - return support.scrapertools.find_single_match(data, '<a href="([^"]+)') - -host = config.get_channel_url(findhost) -headers = [['Referer', host]] - -@support.menu -def mainlist(item): - - film = ["/film/"] - anime = ["/genere/anime/"] - tvshow = ["/serietv/"] - top = [('Generi',['', 'genre'])] - - return locals() - - -def search(item, text): - support.info("[streamingaltadefinizione.py] " + item.url + " search " + text) - item.url = item.url + "/?s=" + text - try: - return support.dooplay_search(item) - except: - import sys - for line in sys.exc_info(): - support.logger.error("%s" % line) - return [] - - -@support.scrape -def genre(item): - patronMenu = '<a href="(?P<url>[^"#]+)">(?P<title>[a-zA-Z]+)' - patronBlock='<a href="#">Genere</a><ul class="sub-menu">(?P<block>.*?)</ul>' - action='peliculas' - - return locals() - - -def peliculas(item): - return support.dooplay_peliculas(item, True if "/genere/" in item.url else False) - - -def episodios(item): - return support.dooplay_get_episodes(item) - - -def findvideos(item): - itemlist = [] - matches = support.match(item, patron=r'<a href="([^"]+)[^>]+>Download[^>]+>[^>]+>[^>]+><strong class="quality">([^<]+)<').matches - for url, quality in matches: - itemlist.append( - item.clone(caction="play", - url=unquote(support.match(url, patron=[r'dest=([^"]+)"',r'/(http[^"]+)">Click']).match), - quality=quality)) - - return support.server(item, itemlist=itemlist) diff --git a/channels/streamingcommunity.py b/channels/streamingcommunity.py index a77e7639..384bbbe1 100644 --- a/channels/streamingcommunity.py +++ b/channels/streamingcommunity.py @@ -113,9 +113,8 @@ def newest(category): def peliculas(item): - # getHeaders() logger.debug() - + if item.mainThumb: item.thumbnail = item.mainThumb global host itemlist = [] items = [] @@ -159,17 +158,19 @@ def peliculas(item): itemlist.sort(key=lambda item: item.n) if not item.newest: + item.mainThumb = item.thumbnail if recordlist: itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'), thumbnail=support.thumb(), page=page, records=recordlist)) elif len(itemlist) >= 20: itemlist.append(item.clone(title=support.typo(support.config.get_localized_string(30992), 'color kod bold'), thumbnail=support.thumb(), records=[], page=page + 1)) support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - + support.check_trakt(itemlist) return itemlist def makeItem(n, it, item): info = session.post(host + '/api/titles/preview/{}'.format(it['id']), headers=headers).json() + logger.debug(jsontools.dump(it)) title = info['name'] lang = 'Sub-ITA' if 'sub-ita' in title.lower() else 'ITA' title = support.cleantitle(re.sub('\[|\]|[Ss][Uu][Bb]-[Ii][Tt][Aa]', '', title)) @@ -203,7 +204,7 @@ def episodios(item): js = json.loads(support.match(item.url, patron=r'seasons="([^"]+)').match.replace('"','"')) for episodes in js: - logger.debug(jsontools.dump(js)) + # logger.debug(jsontools.dump(js)) for it in episodes['episodes']: itemlist.append( @@ -225,16 +226,12 @@ def episodios(item): if config.get_setting('episode_info') and not support.stackCheck(['add_tvshow', 'get_newest']): support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - + support.check_trakt(itemlist) support.videolibrary(itemlist, item) support.download(itemlist, item) return itemlist -def findvideos(item): - itemlist = [item.clone(title = channeltools.get_channel_parameters(item.channel)['title'], server='directo')] - return support.server(item, itemlist=itemlist) - def findvideos(item): itemlist = [item.clone(title = channeltools.get_channel_parameters(item.channel)['title'], server='directo')] return support.server(item, itemlist=itemlist) @@ -246,8 +243,12 @@ def play(item): data = support.httptools.downloadpage(item.url + item.episodeid, headers=headers).data.replace('"','"').replace('\\','') scws_id = support.match(data, patron=r'scws_id"\s*:\s*(\d+)').match + # support.dbg() if not scws_id: + if '<strong>Prossimamente' in data: + platformtools.dialog_ok('StreamingCommunity', 'Il sito notifica che il contenuto sarà disponibile prossimamente') + platformtools.play_canceled = True return [] # Calculate Token @@ -255,6 +256,21 @@ def play(item): expires = int(time() + 172800) token = b64encode(md5('{}{} Yc8U6r8KjAKAepEA'.format(expires, client_ip).encode('utf-8')).digest()).decode('utf-8').replace('=', '').replace('+', '-').replace('/', '_') - url = 'https://scws.xyz/master/{}?token={}&expires={}&n=1|User-Agent={}&Referer={}'.format(scws_id, token, expires, httptools.get_user_agent(), host) + url = 'https://scws.xyz/master/{}?token={}&expires={}&n=1'.format(scws_id, token, expires) + subs = [] + urls = [] - return [item.clone(title = channeltools.get_channel_parameters(item.channel)['title'], server='directo', url=url, manifest='hls')] + info = support.match(url, patron=r'LANGUAGE="([^"]+)",\s*URI="([^"]+)|RESOLUTION=\d+x(\d+).*?(http[^"\s]+)').matches + if info: + for lang, sub, res, url in info: + if sub: + if lang == 'auto': lang = 'ita-forced' + s = config.get_temp_file(lang +'.srt') + subs.append(s) + filetools.write(s, support.vttToSrt(httptools.downloadpage(support.match(sub, patron=r'(http[^\s\n]+)').match).data)) + elif url: + urls.append(['hls [{}]'.format(res), url]) + + return [item.clone(title = channeltools.get_channel_parameters(item.channel)['title'], server='directo', video_urls=urls, subtitle=subs, manifest='hls')] + else: + return [item.clone(title = channeltools.get_channel_parameters(item.channel)['title'], server='directo', url=url, manifest='hls')] diff --git a/channels/streamingita.py b/channels/streamingita.py index 4ee61bc7..a8ada044 100644 --- a/channels/streamingita.py +++ b/channels/streamingita.py @@ -3,7 +3,7 @@ # Canale per streamingITA # ------------------------------------------------------------ -from core import support, httptools +from core import httptools, support from platformcode import logger, config host = config.get_channel_url() @@ -34,7 +34,8 @@ def search(item, text): def peliculas(item): - return support.dooplay_peliculas(item, False) + mixed = True if item.contentType == 'undefined' else False + return support.dooplay_peliculas(item, mixed) def episodios(item): @@ -53,7 +54,7 @@ def findvideos(item): @support.scrape def menu(item): action = 'peliculas' - # debug = True + item.contentType = 'undefined' if item.args in ['genres', 'releases']: patronBlock = r'<nav class="' + item.args + r'">(?P<block>.*?)</nav' patronMenu= r'<a href="(?P<url>[^"]+)"[^>]*>(?P<title>[^<]+)<' diff --git a/channels/tantifilm.py b/channels/tantifilm.py index 30f1bace..e41e0936 100644 --- a/channels/tantifilm.py +++ b/channels/tantifilm.py @@ -54,7 +54,7 @@ def search(item, texto): item.url = host + "/?s=" + texto try: - item.contentType = 'undefined' + item.args = 'search' return peliculas(item) # Continua la ricerca in caso di errore @@ -78,11 +78,11 @@ def newest(categoria): @support.scrape def peliculas(item): - if item.contentType == 'undefined': - action = 'check' + action = 'check' + item.contentType = 'undefined' + if item.args == 'search': patron = r'<a href="(?P<url>[^"]+)" title="Permalink to\s*(?P<title>[^"]+) \((?P<year>[0-9]+)[^<]*\)[^"]*"[^>]+>\s*<img[^s]+src="(?P<thumb>[^"]+)".*?<div class="calitate">\s*<p>(?P<quality>[^<]+)<\/p>' else: - action = 'findvideos' if item.contentType == 'movie' else 'episodios' patronNext = r'<a class="nextpostslink" rel="next" href="([^"]+)">' patron = r'<div class="mediaWrap mediaWrapAlt">\s*<a href="(?P<url>[^"]+)"(?:[^>]+)?>?\s*(?:<img[^s]+src="(?P<thumb>[^"]+)"[^>]+>\s*)?<\/a>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+?)(?P<lang>[sS][uU][bB]\-[iI][tT][aA]+)?(?:[ ]?\((?P<year>\d{4})-?(?:\d{4})?)\).[^<]+[^>]+><\/a>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*(?P<quality>[a-zA-Z-0-9\.]+)?' patronBlock = r'<div id="main_col">(?P<block>.*?)<!\-\- main_col \-\->' @@ -124,6 +124,7 @@ def episodios(item): if res.result(): data += res.result() patron = r'(?P<season>\d+)x(?P<episode>\d+)\s*-\s*(?P<title>[^\|]+)\|(?P<url>[^ ]+)' + # debug = True action = 'findvideos' def itemlistHook(itemlist): @@ -139,14 +140,14 @@ def check(item): if 'sub' in check.lower(): item.contentLanguage = 'Sub-ITA' logger.debug("CHECK : ", check) - if 'anime' in check.lower(): - item.contentType = 'tvshow' - logger.debug('select = ### è una anime ###') - try: - return episodios(item) - except: - pass - elif 'serie' in check.lower(): + # if 'anime' in check.lower(): + # item.contentType = 'tvshow' + # logger.debug('select = ### è una anime ###') + # try: + # return episodios(item) + # except: + # pass + if 'serie' in check.lower(): item.contentType = 'tvshow' return episodios(item) else: diff --git a/channels/tapmovie.json b/channels/tapmovie.json deleted file mode 100644 index c2c73584..00000000 --- a/channels/tapmovie.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "tapmovie", - "name": "Tap Movie", - "language": ["ita", "sub-ita"], - "active": false, - "thumbnail": "tapmovie.png", - "banner": "tapmovie.png", - "categories": ["movie", "tvshow", "anime"], - "not_active": ["include_in_newest"], - "settings": [] -} diff --git a/channels/tapmovie.py b/channels/tapmovie.py deleted file mode 100644 index 76459651..00000000 --- a/channels/tapmovie.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per 'dvdita' - -from core import support, httptools -from core.item import Item -import sys -if sys.version_info[0] >= 3: from concurrent import futures -else: from concurrent_py2 import futures - -host = support.config.get_channel_url() -api_url = '/api/v2/' -per_page = 24 - - -@support.menu -def mainlist(item): - film = ['/browse/movie'] - tvshow = ['/browse/tvshow'] - search = '' - - # [Voce Menu,['url','action','args',contentType] - top = [('Generi', ['', 'genres', '', 'undefined'])] - - return locals() - - -def episodios(item): - support.info(item) - itemlist = [] - - with futures.ThreadPoolExecutor() as executor: - thL = [] - for season in httptools.downloadpage(host + api_url + 'tvshow', post={'tvshow_id': item.id}).json.get('season', []): - season_id = season['season_number'] - thL.append(executor.submit(httptools.downloadpage, host + api_url + 'episodes', post={'tvshow_id': item.id, 'season_id': season_id})) - for th in futures.as_completed(thL): - for episode in th.result().json.get('episodes', []): - itemlist.append(item.clone(action="findvideos", contentSeason=episode['season_id'], contentEpisodeNumber=episode['episode_number'], id=item.id, - title=episode['season_id']+'x'+episode['episode_number'], contentType='episode')) - support.scraper.sort_episode_list(itemlist) - support.videolibrary(itemlist, item) - support.download(itemlist, item) - - return itemlist - - -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) - - -def peliculas(item, text=''): - support.info('search', item) - itemlist = [] - filter_type = False - if item.genre: - text = item.genre - cmd = 'search/category' - else: - cmd = 'search' - if not text: - filter_type = True - - try: - page = int(item.url.split('?p=')[1]) - except: - page = 1 - results = httptools.downloadpage(host + api_url + cmd, post={'search': text, 'page': page}).json.get('results', []) - for result in results: - contentType = 'movie' if result['type'] == 'FILM' else 'tvshow' - if not filter_type or (filter_type and contentType == item.contentType): - itemlist.append(item.clone(id=result.get('id'), title=result.get('title'), contentTitle=result.get('title'), - contentSerieName='' if contentType == 'movie' else result.get('title'), - contentPlot=result.get('description'), thumbnail=result.get('poster'), - fanart=result.get('backdrop'), year=result.get('year'), action='episodios' if contentType == 'tvshow' else 'findvideos', - url='{}/{}/{}-{}'.format('https://filmigratis.org', contentType, result.get('id'), support.scrapertools.slugify(result.get('title'))), - contentType=contentType)) - support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - - if len(results) >= per_page: - page += 1 - support.nextPage(itemlist, item, next_page='https://filmigratis.org/category/' + str(item.n) + '/' + item.genre + '?p=' + str(page)) - return itemlist - - -def search(item, text): - return peliculas(item, text) - - -def findvideos(item): - itemlist = [] - if not item.contentSeason: # film - json = httptools.downloadpage(host + api_url + 'movie', post={'movie_id': item.id}).json - else: - json = httptools.downloadpage(host + api_url + 'episode/links', post={'tvshow_id': item.id, 'season_id': item.contentSeason, 'episode_id': item.contentEpisodeNumber}).json - - for i in json.get('links', []) + json.get('special', []): - itemlist.append(Item(url=i.get('link'))) - return support.server(item, itemlist=itemlist) diff --git a/channels/vedohd.json b/channels/vedohd.json deleted file mode 100644 index 51a47d4d..00000000 --- a/channels/vedohd.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "vedohd", - "name": "VedoHD", - "language": ["ita"], - "active": false, - "thumbnail": "vedohd.png", - "banner": "vedohd.png", - "categories": ["movie"], - "settings": [] -} diff --git a/channels/vedohd.py b/channels/vedohd.py deleted file mode 100644 index ffb81a21..00000000 --- a/channels/vedohd.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------ -# Canale per vedohd -# ------------------------------------------------------------ - -from core import scrapertools, support, autoplay -from platformcode import logger, config - -host = config.get_channel_url() -headers = "" - -IDIOMAS = {'Italiano': 'IT'} -list_language = IDIOMAS.values() - - - -#esclusione degli articoli 'di servizio' -blacklist = ['CB01.UNO ▶ TROVA L’INDIRIZZO UFFICIALE ', 'AVVISO IMPORTANTE – CB01.UNO', 'GUIDA VEDOHD'] - -@support.menu -def mainlist(item): - - film = [ - ('I più votati', ["ratings/?get=movies", 'peliculas']), - ('I più popolari', ["trending/?get=movies", 'peliculas']), - ('Generi', ['ratings/?get=movies', 'menu', 'genres']), - ('Anno', ["", 'menu', 'releases']), - ] - return locals() - - -def search(item, text): - logger.info("search",text) - item.url = item.url + "/?s=" + text - - return support.dooplay_search(item, blacklist) - - -def peliculas(item): - return support.dooplay_peliculas(item, False, blacklist) - - -def findvideos(item): - itemlist = [] - for link in support.dooplay_get_links(item, host): - if link['title'] != 'Trailer': - server, quality = scrapertools.find_single_match(link['title'], '([^ ]+) ?(HD|3D)?') - if quality: - title = server + " [COLOR blue][" + quality + "][/COLOR]" - else: - title = server - itemlist.append(item.clone(action="play", title=title, url=link['url'], server=server, quality=quality,)) - - autoplay.start(itemlist, item) - - return itemlist - - -@support.scrape -def menu(item): - return support.dooplay_menu(item, item.args) - - -def play(item): - logger.debug() - - data = support.swzz_get_url(item) - - return support.server(item, data, headers=headers) diff --git a/channels/vvvvid.py b/channels/vvvvid.py index 645913fb..d2f3e127 100644 --- a/channels/vvvvid.py +++ b/channels/vvvvid.py @@ -90,6 +90,7 @@ def search(item, text): def newest(categoria): item = support.Item() item.args = 'channel/10007/last/' + item.newest = True if categoria == 'peliculas': item.contentType = 'movie' item.url = main_host + 'film/' @@ -133,24 +134,25 @@ def peliculas(item): make_itemlist(itemlist, item, json_file) itlist = [] - for i, it in enumerate(itemlist): - if pagination and (item.page - 1) * pagination > i: continue # pagination - if pagination and i >= item.page * pagination: break # pagination + if not item.newest: + for i, it in enumerate(itemlist): + if pagination and (item.page - 1) * pagination > i: continue # pagination + if pagination and i >= item.page * pagination: break # pagination - itlist.append(it) + itlist.append(it) - if pagination and len(itemlist) >= pagination: - if inspect.stack()[1][3] != 'get_newest': - itlist.append( - item.clone(action='peliculas', - title=support.typo(config.get_localized_string(30992), 'color kod bold'), - fulltitle=item.fulltitle, - show=item.show, - url=item.url, - args=item.args, - page=item.page + 1, - thumbnail=support.thumb())) - itemlist = itlist + if pagination and len(itemlist) >= pagination: + if inspect.stack()[1][3] != 'get_newest': + itlist.append( + item.clone(action='peliculas', + title=support.typo(config.get_localized_string(30992), 'color kod bold'), + fulltitle=item.fulltitle, + show=item.show, + url=item.url, + args=item.args, + page=item.page + 1, + thumbnail=support.thumb())) + itemlist = itlist if 'category' in item.args: support.thumb(itemlist,genre=True) diff --git a/core/autoplay.py b/core/autoplay.py index 1d219823..98964f70 100644 --- a/core/autoplay.py +++ b/core/autoplay.py @@ -29,6 +29,8 @@ def start(itemlist, item): if item.global_search or item.from_action or item.contentAction: # from_action means that's a special function calling this (ex: add to videolibrary) return itemlist + if len([s for s in itemlist if s.server]) == 1: + return itemlist logger.debug() global PLAYED diff --git a/core/item.py b/core/item.py index 73f0f928..38d93fd1 100644 --- a/core/item.py +++ b/core/item.py @@ -355,7 +355,7 @@ class Item(object): dump = "".encode("utf8") return str(urllib.quote(base64.b64encode(dump))) - def fromurl(self, url): + def fromurl(self, url, silent=False): """ Generate an item from a text string. The string can be created by the tourl () function or have the old format: plugin: //plugin.video.kod/? channel = ... (+ other parameters) @@ -369,7 +369,7 @@ class Item(object): decoded = False try: str_item = base64.b64decode(urllib.unquote(url)) - json_item = json.load(str_item, object_hook=self.toutf8) + json_item = json.load(str_item, object_hook=self.toutf8, silent=silent) if json_item is not None and len(json_item) > 0: self.__dict__.update(json_item) decoded = True diff --git a/core/jsontools.py b/core/jsontools.py index a17b8f91..1ca455fb 100644 --- a/core/jsontools.py +++ b/core/jsontools.py @@ -16,15 +16,22 @@ if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int def load(*args, **kwargs): + silent = False + if 'silent' in kwargs: + silent = kwargs['silent'] + kwargs.pop('silent') + if "object_hook" not in kwargs: kwargs["object_hook"] = to_utf8 try: value = json.loads(*args, **kwargs) except: - logger.error("**NOT** able to load the JSON") - logger.error(traceback.format_exc()) - logger.error('ERROR STACK ' + str(stack()[1][3])) + if not silent: + logger.error("**NOT** able to load the JSON") + logger.error(traceback.format_exc()) + if len(stack()) > 1: + logger.error('ERROR STACK {}'.format(stack()[2]) ) value = {} return value diff --git a/core/scrapertools.py b/core/scrapertools.py index a8466832..07b59bea 100644 --- a/core/scrapertools.py +++ b/core/scrapertools.py @@ -504,3 +504,49 @@ def title_unify(title): u_title = spl[0] if len(spl[0]) > 5 else spl[1] return u_title.strip() + + +def girc(page_data, url, co): + """ + Code adapted from https://github.com/vb6rocod/utils/ + Copyright (C) 2019 vb6rocod + and https://github.com/addon-lab/addon-lab_resolver_Project + Copyright (C) 2021 ADDON-LAB, KAR10S + """ + import re + from core import httptools + hdrs = {'Referer': url} + rurl = 'https://www.google.com/recaptcha/api.js' + aurl = 'https://www.google.com/recaptcha/api2' + key = re.search(r'(?:src="{0}\?.*?render|data-sitekey)="?([^"]+)'.format(rurl), page_data) + if key: + key = key.group(1) + rurl = '{0}?render={1}'.format(rurl, key) + page_data1 = httptools.downloadpage(rurl, headers=hdrs).data + v = re.findall('releases/([^/]+)', page_data1)[0] + rdata = {'ar': 1, + 'k': key, + 'co': co, + 'hl': 'en', + 'v': v, + 'size': 'invisible', + 'cb': '123456789'} + page_data2 = httptools.downloadpage('{0}/anchor?{1}'.format(aurl, httptools.urlparse.urlencode(rdata)), headers=hdrs).data + rtoken = re.search('recaptcha-token.+?="([^"]+)', page_data2) + if rtoken: + rtoken = rtoken.group(1) + else: + return '' + pdata = {'v': v, + 'reason': 'q', + 'k': key, + 'c': rtoken, + 'sa': '', + 'co': co} + hdrs.update({'Referer': aurl}) + page_data3 = httptools.downloadpage('{0}/reload?k={1}'.format(aurl, key), post=pdata, headers=hdrs).data + gtoken = re.search('rresp","([^"]+)', page_data3) + if gtoken: + return gtoken.group(1) + + return '' diff --git a/core/servertools.py b/core/servertools.py index 66d01c0b..748c0b98 100644 --- a/core/servertools.py +++ b/core/servertools.py @@ -254,7 +254,7 @@ def resolve_video_urls_for_playing(server, url, video_password="", muestra_dialo if isinstance(video_password, list): return video_password, len(video_password) > 0, "<br/>".join(error_messages) logger.info("Server: %s, url is good" % server) - video_urls.append(["%s [%s]" % (urlparse.urlparse(url)[2][-4:], config.get_localized_string(30137)), url]) + video_urls.append(["%s [%s]" % (urlparse.urlparse(url)[2].split('|')[0][-4:], config.get_localized_string(30137)), url]) # Find out the video URL else: diff --git a/core/support.py b/core/support.py index c9989fba..0bab5a65 100755 --- a/core/support.py +++ b/core/support.py @@ -604,11 +604,11 @@ def scrape(func): if function == 'episodios': autorenumber.start(itemlist, item) else: autorenumber.start(itemlist) - if action != 'play' and 'patronMenu' not in args and not disabletmdb and function != 'episodios' \ - and item.contentType in ['movie', 'tvshow', 'episode', 'undefined']: + if action != 'play' and 'patronMenu' not in args and 'patronGenreMenu' not in args \ + and not stackCheck(['add_tvshow', 'get_newest']) and (function not in ['episodes', 'mainlist'] \ + or (function in ['episodes'] and config.get_setting('episode_info'))): tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) - if not group and not args.get('groupExplode') and ((pagination and len(matches) <= pag * pagination) or not pagination): # next page with pagination if patronNext and inspect.stack()[1][3] not in ['newest'] and len(inspect.stack()) > 2 and inspect.stack()[2][3] not in ['get_channel_results']: nextPage(itemlist, item, data, patronNext, function) @@ -655,9 +655,7 @@ def scrape(func): # itemlist = filterLang(item, itemlist) # causa problemi a newest - if config.get_setting('trakt_sync'): - from core import trakt_tools - trakt_tools.trakt_check(itemlist) + check_trakt(itemlist) return itemlist return wrapper @@ -731,6 +729,7 @@ def dooplay_search(item, blacklist=""): def dooplay_search_vars(item, blacklist): + actLike = 'peliculas' if item.contentType == 'undefined': # ricerca globale type = '(?P<type>movies|tvshows)' typeActionDict = {'findvideos': ['movies'], 'episodios': ['tvshows']} @@ -1280,26 +1279,23 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru videoitem.server = videoitem.server.lower() if videoitem.video_urls or srv_param.get('active', False): - title = typo(item.contentTitle.strip(), 'bold') if item.contentType == 'movie' or (config.get_localized_string(30161) in item.title) else item.title + vi = item.clone(server=videoitem.server, + extraInfo=videoitem.extraInfo, + serverName=videoitem.serverName, + url=videoitem.url, + videoUrls= videoitem.videoUrlsn, + ch_name=channeltools.get_channel_parameters(item.channel)['title'], + action = "play") - quality = videoitem.quality if videoitem.quality else item.quality if item.quality else '' - videoitem.title = (title if item.channel not in ['url'] else '')\ - + (typo(videoitem.title, '_ color kod [] bold') if videoitem.title else "")\ - + (typo(videoitem.quality, '_ color kod []') if videoitem.quality else "")\ - + (typo(videoitem.contentLanguage, '_ color kod []') if videoitem.contentLanguage else "")\ - + (typo(videoitem.extraInfo, '_ color kod []') if videoitem.extraInfo else "") - videoitem.plot = typo(videoitem.title, 'bold') + (typo(quality, '_ [] bold') if quality else '') - videoitem.channel = item.channel - videoitem.fulltitle = item.fulltitle - videoitem.show = item.show - if not videoitem.video_urls: videoitem.thumbnail = item.thumbnail - videoitem.contentType = item.contentType - videoitem.infoLabels = item.infoLabels - videoitem.quality = quality - videoitem.referer = item.referer if item.referer else item.url - videoitem.action = "play" - # videoitem.nfo = item.nfo - # videoitem.strm_path = item.strm_path + if videoitem.title: vi.serverName = videoitem.title + if videoitem.quality: vi.quality = videoitem.quality + if not vi.referer: vi.referer = item.url + vi.contentFanart = item.infoLabels['fanart'] + vi.contentThumb = item.infoLabels['fanart'] + if videoitem.forcethumb: + vi.thumbnail = videoitem.thumbnail + vi.forcethumb = True + videoitem = vi return videoitem # non threaded for webpdb @@ -1409,7 +1405,7 @@ def addQualityTag(item, itemlist, data, patron): "DTS": "audio ricavato dai dischi DTS2, quindi la qualità audio è elevata.", "LD": "l’audio è stato registrato tramite jack collegato alla macchina da presa, pertanto di discreta qualità.", "DD": "audio ricavato dai dischi DTS cinema. L’audio è di buona qualità, ma potreste riscontrare il fatto che non potrebbe essere più riproducibile.", - "AC3": "audio in Dolby Digital puo' variare da 2.0 a 5.1 canali in alta qualità.", + "AC3": "audio in Dolby Digital può variare da 2.0 a 5.1 canali in alta qualità.", "MP3": "codec per compressione audio utilizzato MP3.", "RESYNC": "il film è stato lavorato e re sincronizzato con una traccia audio. A volte potresti riscontrare una mancata sincronizzazione tra audio e video.", } @@ -1436,7 +1432,7 @@ def addQualityTag(item, itemlist, data, patron): descr = '' itemlist.insert(0,Item(channel=item.channel, action="", - title=typo(qualityStr, '[] color kod bold'), + title=typo(qualityStr, 'bold'), fulltitle=qualityStr, plot=descr, folder=False, @@ -1600,3 +1596,45 @@ def thumb(item_itemlist_string=None, genre=False, live=False): else: return get_thumb('next.png') + + +def vttToSrt(data): + # Code adapted by VTT_TO_SRT.PY (c) Jansen A. Simanullang + ret = '' + + data = re.sub(r'(\d\d:\d\d:\d\d).(\d\d\d) --> (\d\d:\d\d:\d\d).(\d\d\d)(?:[ \-\w]+:[\w\%\d:]+)*\n', r'\1,\2 --> \3,\4\n', data) + data = re.sub(r'(\d\d:\d\d).(\d\d\d) --> (\d\d:\d\d).(\d\d\d)(?:[ \-\w]+:[\w\%\d:]+)*\n', r'00:\1,\2 --> 00:\3,\4\n', data) + data = re.sub(r'(\d\d).(\d\d\d) --> (\d\d).(\d\d\d)(?:[ \-\w]+:[\w\%\d:]+)*\n', r'00:00:\1,\2 --> 00:00:\3,\4\n', data) + data = re.sub(r'WEBVTT\n', '', data) + data = re.sub(r'Kind:[ \-\w]+\n', '', data) + data = re.sub(r'Language:[ \-\w]+\n', '', data) + data = re.sub(r'<c[.\w\d]*>', '', data) + data = re.sub(r'</c>', '', data) + data = re.sub(r'<\d\d:\d\d:\d\d.\d\d\d>', '', data) + data = re.sub(r'::[\-\w]+\([\-.\w\d]+\)[ ]*{[.,:;\(\) \-\w\d]+\n }\n', '', data) + data = re.sub(r'Style:\n##\n', '', data) + + lines = data.split(os.linesep) + + for n, line in enumerate(lines): + if re.match(r"((\d\d:){2}\d\d),(\d{3}) --> ((\d\d:){2}\d\d),(\d{3})", line): + ret += str(n + 1) + os.linesep + line + os.linesep + else: + ret += line + os.linesep + + return ret + +def check_trakt(itemlist): + if config.get_setting('trakt_sync'): + from core import trakt_tools + trakt_tools.trakt_check(itemlist) + return itemlist + + +def stackCheck(values): + stacks = [s[3] for s in inspect.stack()] + logger.debug('STAKS', stacks) + if type(values) == str: + return values in stacks + else: + return any(v in values for v in stacks) \ No newline at end of file diff --git a/core/tmdb.py b/core/tmdb.py index 92cd2c43..1572f560 100644 --- a/core/tmdb.py +++ b/core/tmdb.py @@ -393,18 +393,17 @@ def set_infoLabels_item(item, seekTmdb=True, search_language=def_lang): if search_type == 'tv': # Serial search by title and filtering your results if necessary searched_title = scrapertools.unescape(item.infoLabels['tvshowtitle']) - # searched_title = searched_title.split('-')[0].strip() - otmdb = Tmdb(searched_text=searched_title, search_type=search_type, - search_language=search_language, filtro=item.infoLabels.get('filtro', {}), - year=item.infoLabels['year']) else: # Movie search by title ... # if item.infoLabels['year'] or item.infoLabels['filtro']: # ...and year or filter searched_title = scrapertools.unescape(item.infoLabels['title']) - # searched_title = searched_title.split('-')[0].strip() + # from core.support import dbg;dbg() + otmdb = Tmdb(searched_text=searched_title, search_type=search_type, search_language=search_language, + filtro=item.infoLabels.get('filtro', {}), year=item.infoLabels['year']) + if otmdb is not None and not otmdb.get_id(): otmdb = Tmdb(searched_text=searched_title, search_type=search_type, search_language=search_language, - filtro=item.infoLabels.get('filtro', {}), year=item.infoLabels['year']) + filtro=item.infoLabels.get('filtro', {})) if otmdb is not None: if otmdb.get_id() and config.get_setting("tmdb_plus_info", default=False): # If the search has been successful and you are not looking for a list of items, @@ -471,10 +470,9 @@ def find_and_set_infoLabels(item): item.infoLabels['year'] = year[1:-1] if not item.infoLabels.get("tmdb_id") or not item.infoLabels.get("tmdb_id")[0].isdigit(): - if not item.infoLabels.get("imdb_id"): - otmdb_global = Tmdb(searched_text=scrapertools.unescape(title), search_type=search_type, year=item.infoLabels['year']) - else: - otmdb_global = Tmdb(external_id=item.infoLabels.get("imdb_id"), external_source="imdb_id", search_type=search_type) + if item.infoLabels.get("imdb_id"): otmdb_global = Tmdb(external_id=item.infoLabels.get("imdb_id"), external_source="imdb_id", search_type=search_type) + else: otmdb_global = Tmdb(searched_text=scrapertools.unescape(title), search_type=search_type, year=item.infoLabels['year']) + elif not otmdb_global or str(otmdb_global.result.get("id")) != item.infoLabels['tmdb_id']: otmdb_global = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], search_type=search_type, search_language=def_lang) @@ -537,10 +535,7 @@ def get_nfo(item, search_groups=False): info_nfo = 'https://www.themoviedb.org/tv/{}/episode_group/{}'.format(item.infoLabels['tmdb_id'], Id) return info_nfo + '\n' else: return - # from core.support import dbg;dbg() - # if "season" in item.infoLabels and "episode" in item.infoLabels: - # info_nfo = "https://www.themoviedb.org/tv/{}/season/{}/episode/{}" .format(item.infoLabels['tmdb_id'], item.contentSeason, item.contentEpisodeNumber) - # else: + info_nfo = ', '.join(item.infoLabels['url_scraper']) return info_nfo + '\n' @@ -644,10 +639,11 @@ class ResultDictDefault(dict): def __missing__(self, key): """ - default values ​​in case the requested key does not exist + default values in case the requested key does not exist """ if key in ['genre_ids', 'genre', 'genres']: return list() + elif key == 'images_posters': posters = dict() if 'images' in list(super(ResultDictDefault, self).keys()) and 'posters' in super(ResultDictDefault, self).__getitem__('images'): diff --git a/core/trakt_tools.py b/core/trakt_tools.py index bf00588a..90d81207 100644 --- a/core/trakt_tools.py +++ b/core/trakt_tools.py @@ -3,11 +3,14 @@ # -*- Created for Alfa-addon -*- # -*- By the Alfa Develop Group -* +#from builtins import str + import os, xbmc -from core import httptools, jsontools +from core import httptools, jsontools from core.item import Item from platformcode import config, logger from threading import Thread + import sys if sys.version_info[0] >= 3: from concurrent import futures else: from concurrent_py2 import futures @@ -26,7 +29,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.trakt.tv/oauth/device/code" + url = "http://api-v2launch.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 +60,13 @@ def token_trakt(item): try: if item.extra == "renew": refresh = config.get_setting("refresh_token_trakt", "trakt") - url = "http://api.trakt.tv/oauth/device/token" + url = "https://api.trakt.tv/oauth/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 = httptools.downloadpage(url, post=post).data data = jsontools.load(data) elif item.action == "token_trakt": - url = "http://api.trakt.tv/oauth/device/token" + url = "https://api-v2launch.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 +85,7 @@ def token_trakt(item): config.set_setting("trakt_sync", False) return - url = "http://api.trakt.tv/oauth/device/token" + url = "http://api-v2launch.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 @@ -106,9 +108,7 @@ def token_trakt(item): config.set_setting("refresh_token_trakt", refresh, "trakt") if not item.folder: platformtools.dialog_notification(config.get_localized_string(60255), config.get_localized_string(60256)) - if config.is_xbmc(): - import xbmc - xbmc.executebuiltin("Container.Refresh") + xbmc.executebuiltin("Container.Refresh") return except: @@ -166,8 +166,12 @@ def get_trakt_watched(id_type, mediatype, update=False): if token_auth: headers.append(['Authorization', "Bearer %s" % token_auth]) url = "https://api.trakt.tv/sync/watched/%s" % mediatype - data = httptools.downloadpage(url, headers=headers).data - watched_dict = jsontools.load(data) + data = httptools.downloadpage(url, headers=headers) + if data.code == 401: + token_trakt(Item(extra="renew")) + return get_trakt_watched(id_type, mediatype, update) + + watched_dict = jsontools.load(data.data) if mediatype == 'shows': @@ -266,14 +270,12 @@ def ask_install_script(): def wait_for_update_trakt(): logger.debug() - t = Thread(target=update_all) + t = Thread(update_all) t.setDaemon(True) t.start() t.is_alive() - def update_all(): - # from core.support import dbg;dbg() from time import sleep logger.debug() sleep(20) @@ -282,4 +284,3 @@ def update_all(): for mediatype in ['movies', 'shows']: trakt_data = get_trakt_watched('tmdb', mediatype, True) update_trakt_data(mediatype, trakt_data) - diff --git a/core/videolibrarytools.py b/core/videolibrarytools.py index af429ee6..09e47674 100644 --- a/core/videolibrarytools.py +++ b/core/videolibrarytools.py @@ -974,7 +974,7 @@ def add_movie(item): @param item: item to be saved. """ logger.debug() - from platformcode.launcher import set_search_temp; set_search_temp(item) + # from platformcode.launcher import set_search_temp; set_search_temp(item) item.contentType = 'movie' # To disambiguate titles, TMDB is caused to ask for the really desired title @@ -1023,7 +1023,7 @@ def add_tvshow(item, channel=None, itemlist=[]): logger.debug("show=#" + item.show + "#") item.contentType = 'tvshow' - from platformcode.launcher import set_search_temp; set_search_temp(item) + # from platformcode.launcher import set_search_temp; set_search_temp(item) if item.channel == "downloads": itemlist = [item.clone()] diff --git a/lib/unshortenit.py b/lib/unshortenit.py index e7b2dd03..25b83381 100644 --- a/lib/unshortenit.py +++ b/lib/unshortenit.py @@ -695,14 +695,13 @@ class UnshortenIt(object): return httptools.downloadpage(uri, only_headers=True, follow_redirects=False).headers.get('location', uri), 200 def _unshorten_uprot(self, uri): - from core.support import dbg - dbg() for link in scrapertools.find_multiple_matches(httptools.downloadpage(uri, cloudscraper=True).data, '<a[^>]+href="([^"]+)'): if link.startswith('https://maxstream.video') or link.startswith('https://uprot.net') and link != uri: return link, 200 return uri, 200 + def decrypt_aes(text, key): try: from Cryptodome.Cipher import AES @@ -775,3 +774,25 @@ def findlinks(text): else: text += '\n' + str(link.result()[0]) return text + + +class FileCrypt: + def __init__(self, uri=None): + self.uri = uri + + def find(self, data): + _filecrypt_regex = r'https?://\w+\.filecrypt\.cc/[a-zA-Z0-9_=/]+' + return scrapertools.find_multiple_matches(data, _filecrypt_regex) + + def list_files(self): + reg = """<td title="([^"]+).*?<button onclick="openLink\('([^']+)""" + data = httptools.downloadpage(self.uri).data + ret = scrapertools.find_multiple_matches(data, reg) + return ret + + def unshorten(self, link): + link_data = httptools.downloadpage('https://www.filecrypt.cc/Link/' + link + '.html').data + time.sleep(0.1) + url = httptools.downloadpage(scrapertools.find_single_match(link_data, "location.href='([^']+)"), headers={'Referer': 'http://www.filecrypt.cc/'}, only_headers=True).url + logger.info(url) + return url diff --git a/platformcode/config.py b/platformcode/config.py index 0716d42a..f0a145eb 100644 --- a/platformcode/config.py +++ b/platformcode/config.py @@ -74,16 +74,21 @@ def get_platform(full_version=False): codename = {"10": "dharma", "11": "eden", "12": "frodo", "13": "gotham", "14": "helix", "15": "isengard", "16": "jarvis", "17": "krypton", "18": "leia", - "19": "matrix"} - code_db = {'10': 'MyVideos37.db', '11': 'MyVideos60.db', '12': 'MyVideos75.db', + "19": "matrix", '20': 'nexus'} + video_db = {'10': 'MyVideos37.db', '11': 'MyVideos60.db', '12': 'MyVideos75.db', '13': 'MyVideos78.db', '14': 'MyVideos90.db', '15': 'MyVideos93.db', '16': 'MyVideos99.db', '17': 'MyVideos107.db', '18': 'MyVideos116.db', - '19': 'MyVideos119.db'} + '19': 'MyVideos119.db', '20': 'MyVideos120.db'} + view_db = {'10': 'ViewModes1.db', '11': 'ViewModes4.db', '12': 'ViewModes4.db', + '13': 'ViewModes6.db', '14': 'ViewModes6.db', '15': 'ViewModes6.db', + '16': 'ViewModes6.db', '17': 'ViewModes6.db', '18': 'ViewModes6.db', + '19': 'ViewModes6.db', '20': 'ViewModes6.db'} num_version = xbmc.getInfoLabel('System.BuildVersion') num_version = re.match("\d+\.\d+", num_version).group(0) ret['name_version'] = codename.get(num_version.split('.')[0], num_version) - ret['video_db'] = code_db.get(num_version.split('.')[0], "") + ret['video_db'] = video_db.get(num_version.split('.')[0], "") + ret['view_db'] = view_db.get(num_version.split('.')[0], "") ret['num_version'] = float(num_version) if ret['num_version'] < 14: ret['platform'] = "xbmc-" + ret['name_version'] @@ -443,3 +448,9 @@ def get_online_server_thumb(server): def get_language(): return get_localized_string(20001) + +def get_skin(): + import xbmc + from core import jsontools + js = '{"jsonrpc": "2.0", "method": "Settings.GetSettingValue", "params": {"setting": "lookandfeel.skin"}, "id": 1 }' + return jsontools.load(xbmc.executeJSONRPC(js)).get('result', {}).get('value') diff --git a/platformcode/launcher.py b/platformcode/launcher.py index 461c8275..d9384667 100644 --- a/platformcode/launcher.py +++ b/platformcode/launcher.py @@ -2,27 +2,20 @@ # ------------------------------------------------------------ # XBMC Launcher (xbmc / kodi) # ------------------------------------------------------------ -import datetime -import json -import sys, os - -import requests - -PY3 = False -if sys.version_info[0] >= 3:PY3 = True; unicode = str; unichr = chr; long = int +import sys from core.item import Item -from core import filetools, jsontools -from platformcode import config, logger, platformtools, xbmc_videolibrary +from core import filetools +from platformcode import config, logger, platformtools from platformcode.logger import WebErrorException -temp_search_file = config.get_temp_file('temp-search') def start(): - """ First function that is executed when entering the plugin. + ''' + First function that is executed when entering the plugin. Within this function all calls should go to functions that we want to execute as soon as we open the plugin. - """ + ''' logger.debug() if not config.dev_mode(): @@ -31,124 +24,65 @@ def start(): changelog = fileC.read() if changelog.strip(): platformtools.dialog_ok('Kodi on Demand', 'Aggiornamenti applicati:\n' + changelog) - os.remove(config.changelogFile) + filetools.remove(config.changelogFile) except: pass def run(item=None): logger.debug() + # Extract item from sys.argv + if not item: item = makeItem() - if not item: - # Extract item from sys.argv - if sys.argv[2]: - sp = sys.argv[2].split('&') - url = sp[0] - item = Item().fromurl(url) - if len(sp) > 1: - for e in sp[1:]: - key, val = e.split('=') - item.__setattr__(key, val) - # If no item, this is mainlist - else: - item = Item(channel="channelselector", action="getmainlist", viewmode="movie") - if not config.get_setting('show_once'): - if not config.get_all_settings_addon(): - logger.error('corrupted settings.xml!!') - settings_xml = os.path.join(config.get_data_path(), "settings.xml") - settings_bak = os.path.join(config.get_data_path(), "settings.bak") - if filetools.exists(settings_bak): - filetools.copy(settings_bak, settings_xml, True) - logger.info('restored settings.xml from backup') - else: - filetools.write(settings_xml, '<settings version="2">\n</settings>') # resetted settings - else: - from platformcode import xbmc_videolibrary - xbmc_videolibrary.ask_set_content(silent=False) - config.set_setting('show_once', True) + # Load or Repare Settings + if not config.get_setting('show_once'): showOnce() - logger.info(item.tostring()) - - reload = False - from core import db - if db['OnPlay'].get('addon', False): - reload = True - db['OnPlay']['addon'] = False - db.close() + # Acrions + logger.debug(item.tostring()) try: + # Active tmdb if not config.get_setting('tmdb_active'): config.set_setting('tmdb_active', True) # If item has no action, stops here - if item.action == "": - logger.debug("Item without action") + if item.action == '': + logger.debug('Item without action') return - # Action for main menu in channelselector - elif item.action == "getmainlist": + # Channel Selector + if item.channel == 'channelselector': + itemlist = [] import channelselector - - itemlist = channelselector.getmainlist() - + if item.action == 'getmainlist': # Action for main menu in channelselector + itemlist = channelselector.getmainlist() + elif item.action == 'getchanneltypes': # Action for channel types on channelselector: movies, series, etc. + itemlist = channelselector.getchanneltypes() + elif item.action == 'filterchannels': # Action for channel listing on channelselector + itemlist = channelselector.filterchannels(item.channel_type) platformtools.render_items(itemlist, item) - # Action for channel types on channelselector: movies, series, etc. - elif item.action == "getchanneltypes": - import channelselector - itemlist = channelselector.getchanneltypes() - - platformtools.render_items(itemlist, item) - - # Action for channel listing on channelselector - elif item.action == "filterchannels": - import channelselector - itemlist = channelselector.filterchannels(item.channel_type) - - platformtools.render_items(itemlist, item) # Special action for playing a video from the library - elif item.action == "play_from_library": - play_from_library(item) - return + elif item.action == 'play_from_library': + return playFromLibrary(item) - elif item.action == "keymap": - from platformcode import keymaptools - if item.open: - return keymaptools.open_shortcut_menu() - else: - return keymaptools.set_key() + # Special play action + elif item.action == 'play': play(item) - elif item.channel == "infoplus": - from platformcode import infoplus - return infoplus.Main(item) + # Special findvideos Action + elif item.action == 'findvideos': findvideos(item) - elif item.channel == "backup": - from platformcode import backup - return getattr(backup, item.action)(item) + # Special action for searching, first asks for the words then call the "search" function + elif item.action == 'search': search(item) - elif item.channel == "elementum_download": - from platformcode import elementum_download - return getattr(elementum_download, item.action)(item) + ######## Following shares must be improved ######## - elif item.channel == "shortcuts": - from platformcode import shortcuts - return getattr(shortcuts, item.action)(item) - - elif item.channel == "autorenumber": - from platformcode import autorenumber - return getattr(autorenumber, item.action)(item) - - elif item.action == "delete_key": - from platformcode import keymaptools - return keymaptools.delete_key() - - elif item.action == "script": - from core import tmdb - tmdb.clean_cache() - platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False) + # Special itemInfo Action elif item.action == "itemInfo": platformtools.dialog_textviewer('Item info', item.parent) + + # Special action for open item.url in browser elif item.action == "open_browser": import webbrowser if not webbrowser.open(item.url): @@ -157,6 +91,8 @@ def run(item=None): xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % item.url) else: 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)])) + + # Special gotopage Action elif item.action == "gotopage": page = platformtools.dialog_numeric(0, config.get_localized_string(70513)) if page: @@ -169,163 +105,52 @@ def run(item=None): item.url = re.sub('([=/])[0-9]+(/?)$', '\g<1>' + page + '\g<2>', item.url) xbmc.executebuiltin("Container.Update(%s?%s)" % (sys.argv[0], item.tourl())) - elif reload and item.channel == 'filmontv' and item.action == 'new_search': - platformtools.fakeVideo() - import xbmc - return xbmc.executebuiltin("Container.Update(" + 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")): - CHANNELS = 'channels' + # Special action for adding a movie to the library + elif item.action == "add_pelicula_to_library": + from core import videolibrarytools + videolibrarytools.add_movie(item) + + # Special action for adding a serie to the library + elif item.action == "add_serie_to_library": + channel = importChannel(item) + from core import videolibrarytools + videolibrarytools.add_tvshow(item, channel) + + # Special action for adding a undefined to the library + elif item.action == "add_to_library": + channel = importChannel(item) + 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 + item.action = item.extra + del item.extra + downloads.save_download(item) + + # keymaptools special actions + elif item.action == "keymap": + from platformcode import keymaptools + if item.open: + return keymaptools.open_shortcut_menu() else: - CHANNELS = 'specials' + return keymaptools.set_key() + elif item.action == "delete_key": + from platformcode import keymaptools + return keymaptools.delete_key() - channel_file = os.path.join(config.get_runtime_path(), CHANNELS, item.channel + ".py") + # delete tmdb cache + elif item.action == "script": + from core import tmdb + tmdb.clean_cache() + platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False) - logger.debug("channel_file= " + channel_file + ' - ' + CHANNELS + ' - ' + item.channel) + ################################################ - channel = None + # For all other actions + else: actions(item) - if os.path.exists(channel_file): - try: - channel = __import__('%s.%s' % (CHANNELS, item.channel), None, None, ['%s.%s' % (CHANNELS, item.channel)]) - except ImportError: - exec("import " + CHANNELS + "." + item.channel + " as channel") - - logger.info("Running channel %s | %s" % (channel.__name__, channel.__file__)) - - # Special play action - if item.action == "play": - # define la info para trakt - try: - from core import trakt_tools - trakt_tools.set_trakt_info(item) - except: - pass - logger.debug("item.action=%s" % item.action.upper()) - # logger.debug("item_toPlay: " + "\n" + item.tostring('\n')) - - # First checks if channel has a "play" function - if hasattr(channel, 'play'): - logger.debug("Executing channel 'play' method") - itemlist = channel.play(item) - b_favourite = item.isFavourite - # Play should return a list of playable URLS - if len(itemlist) > 0 and isinstance(itemlist[0], Item): - item = itemlist[0] - if b_favourite: - item.isFavourite = True - platformtools.play_video(item) - - # Permitir varias calidades desde play en el Channel - elif len(itemlist) > 0 and isinstance(itemlist[0], list): - item.video_urls = itemlist - platformtools.play_video(item) - - # If not, shows user an error message - else: - platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339)) - - # If player don't have a "play" function, not uses the standard play from platformtools - else: - logger.debug("Executing core 'play' method") - platformtools.play_video(item) - - # Special action for findvideos, where the plugin looks for known urls - elif item.action == "findvideos": - from core import servertools - if reload: - item.autoplay = True - platformtools.fakeVideo() - - # First checks if channel has a "findvideos" function - if hasattr(channel, 'findvideos'): - itemlist = getattr(channel, item.action)(item) - - # If not, uses the generic findvideos function - else: - logger.debug("No channel 'findvideos' method, " "executing core method") - itemlist = servertools.find_video_items(item) - - if config.get_setting("max_links", "videolibrary") != 0: - itemlist = limit_itemlist(itemlist) - - platformtools.render_items(itemlist, item) - - # Special action for adding a movie to the library - elif item.action == "add_pelicula_to_library": - from core import videolibrarytools - videolibrarytools.add_movie(item) - - # Special action for adding a serie to the library - elif item.action == "add_serie_to_library": - from core import videolibrarytools - videolibrarytools.add_tvshow(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 - item.action = item.extra - del item.extra - downloads.save_download(item) - - # Special action for searching, first asks for the words then call the "search" function - elif item.action == "search": - if filetools.isfile(temp_search_file) and config.get_setting('videolibrary_kodi'): - itemlist = [] - f = filetools.read(temp_search_file) - strList = f.split(',') - if strList[0] == '[V]' and strList[1] == item.channel: - for it in strList: - if it and it not in ['[V]', item.channel]: - itemlist.append(Item().fromurl(it)) - filetools.write(temp_search_file, f[4:]) - return platformtools.render_items(itemlist, item) - else: - filetools.remove(temp_search_file) - - logger.debug("item.action=%s" % item.action.upper()) - from core import channeltools - - if config.get_setting('last_search'): - last_search = channeltools.get_channel_setting('Last_searched', 'search', '') - else: - last_search = '' - - search_text = platformtools.dialog_input(last_search) - - if search_text is not None: - channeltools.set_channel_setting('Last_searched', search_text, 'search') - itemlist = new_search(item.clone(text=search_text), channel) - else: - return - - platformtools.render_items(itemlist, item) - - # For all other actions - else: - - logger.debug("Executing channel '%s' method" % item.action) - itemlist = getattr(channel, item.action)(item) - if config.get_setting('trakt_sync'): - from core import trakt_tools - token_auth = config.get_setting("token_trakt", "trakt") - if not token_auth: - trakt_tools.auth_trakt() - else: - import xbmc - if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting('install_trakt'): - trakt_tools.ask_install_script() - itemlist = trakt_tools.trakt_check(itemlist) - else: - config.set_setting('install_trakt', True) - - platformtools.render_items(itemlist, item) except WebErrorException as e: @@ -337,24 +162,25 @@ def run(item=None): platformtools.dialog_ok( config.get_localized_string(59985) % e.channel, config.get_localized_string(60013) % e.url) + except Exception as e: import traceback from core import scrapertools logger.error(traceback.format_exc()) - patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + r'([^.]+)\.py"' + patron = r'File "{}([^.]+)\.py"'.format(filetools.join(config.get_runtime_path(), 'channels', '').replace('\\', '\\\\')) Channel = scrapertools.find_single_match(traceback.format_exc(), patron) if Channel or e.__class__ == logger.ChannelScraperException: if item.url: if platformtools.dialog_yesno(config.get_localized_string(60087) % Channel, config.get_localized_string(60014), nolabel='ok', yeslabel=config.get_localized_string(70739)): - run(Item(action="open_browser", url=item.url)) + run(Item(action='open_browser', url=item.url)) else: platformtools.dialog_ok(config.get_localized_string(60087) % Channel, config.get_localized_string(60014)) else: if platformtools.dialog_yesno(config.get_localized_string(60038), config.get_localized_string(60015)): - platformtools.itemlist_update(Item(channel="setting", action="report_menu"), True) + platformtools.itemlist_update(Item(channel='setting', action='report_menu'), True) finally: # db need to be closed when not used, it will cause freezes from core import db @@ -374,196 +200,195 @@ def new_search(item, channel=None): writelist = item.channel for it in itemlist: writelist += ',' + it.tourl() - filetools.write(temp_search_file, writelist) + # filetools.write(temp_search_file, writelist) return itemlist -def set_search_temp(item): - if filetools.isfile(temp_search_file) and config.get_setting('videolibrary_kodi'): - f = '[V],' + filetools.read(temp_search_file) - filetools.write(temp_search_file, f) -def reorder_itemlist(itemlist): +def limitItemlist(itemlist): logger.debug() - # logger.debug("Inlet itemlist size: %i" % len(itemlist)) - - new_list = [] - mod_list = [] - not_mod_list = [] - - modified = 0 - not_modified = 0 - - to_change = [[config.get_localized_string(60335), '[V]'], [config.get_localized_string(60336), '[D]']] - - for item in itemlist: - if not PY3: - old_title = unicode(item.title, "utf8").lower().encode("utf8") - else: - old_title = item.title.lower() - for before, after in to_change: - if before in item.title: - item.title = item.title.replace(before, after) - break - - if not PY3: - new_title = unicode(item.title, "utf8").lower().encode("utf8") - else: - new_title = item.title.lower() - if old_title != new_title: - mod_list.append(item) - modified += 1 - else: - not_mod_list.append(item) - not_modified += 1 - - # logger.debug("OLD: %s | NEW: %s" % (old_title, new_title)) - - new_list.extend(mod_list) - new_list.extend(not_mod_list) - - logger.debug("Modified Titles:%i |Unmodified:%i" % (modified, not_modified)) - - if len(new_list) == 0: - new_list = itemlist - - # logger.debug("Outlet itemlist size: %i" % len(new_list)) - return new_list - - -def limit_itemlist(itemlist): - logger.debug() - # logger.debug("Inlet itemlist size: %i" % len(itemlist)) - try: - opt = config.get_setting("max_links", "videolibrary") - if opt == 0: + value = config.get_setting('max_links', 'videolibrary') + if value == 0: new_list = itemlist else: - i_max = 30 * opt - new_list = itemlist[:i_max] - - # logger.debug("Outlet itemlist size: %i" % len(new_list)) + new_list = itemlist[:value] return new_list except: return itemlist -def play_from_library(item): - """ - The .strm files when played from kodi, this expects it to be a "playable" file so it cannot contain - more items, at most a selection dialog can be placed. - We solve this by "cheating kodi" and making him believe that something has been reproduced, so later by - "Container.Update ()" we load the strm as if an item from inside the addon were treated, removing all - the limitations and allowing to reproduce through the general function without having to create new methods to - the video library. - @type item: item - @param item: item with information - """ - - def get_played_time(item): - from core import videolibrarytools - - if item.contentType == 'movie': - nfo_path = item.nfo - if nfo_path.startswith('\\') or nfo_path.startswith('/'): - nfo_path = filetools.join(videolibrarytools.MOVIES_PATH, nfo_path) - - else: - nfo_path =item.strm_path.replace('strm','nfo') - if nfo_path.startswith('\\') or nfo_path.startswith('/'): - nfo_path = filetools.join(videolibrarytools.TVSHOWS_PATH, nfo_path) - - if nfo_path and filetools.isfile(nfo_path): - head_nfo, item_nfo = videolibrarytools.read_nfo(nfo_path) - sleep(1) - played_time = platformtools.get_played_time(item_nfo) - - else: played_time = 0 - - return played_time - - import xbmcgui, xbmcplugin, xbmc - from time import sleep - - if not item.autoplay and not item.next_ep: - platformtools.fakeVideo() - - - itemlist=[] - item.fromLibrary = True - item.window = True +def makeItem(): logger.debug() - - # Modify the action (currently the video library needs "findvideos" since this is where the sources are searched - item.action = item.next_action if item.next_action else "findvideos" - - if item.contentType == 'movie' or item.contentType != 'movie' and config.get_setting('next_ep') < 3: - window_type = config.get_setting("window_type", "videolibrary") - else: window_type = 1 - - # and launch kodi again - if (xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1) or item.action != 'findvideos': - xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")") - + if sys.argv[2]: + sp = sys.argv[2].split('&') + url = sp[0] + item = Item().fromurl(url) + if len(sp) > 1: + for e in sp[1:]: + key, val = e.split('=') + if val.lower() == 'false': val = False + elif val.lower() == 'true': val = True + item.__setattr__(key, val) + # If no item, this is mainlist else: - # Pop-up window - from specials import videolibrary - from core.channeltools import get_channel_parameters + item = Item(channel='channelselector', action='getmainlist', viewmode='movie') + + return item + + +def showOnce(): + if not config.get_all_settings_addon(): + logger.error('corrupted settings.xml!!') + settings_xml = filetools.join(config.get_data_path(), 'settings.xml') + settings_bak = filetools.join(config.get_data_path(), 'settings.bak') + if filetools.exists(settings_bak): + filetools.copy(settings_bak, settings_xml, True) + logger.info('restored settings.xml from backup') + else: + filetools.write(settings_xml, '<settings version="2">\n</settings>') # resetted settings + else: + from platformcode import xbmc_videolibrary + xbmc_videolibrary.ask_set_content(silent=False) + config.set_setting('show_once', True) + + +def play(item): + channel = importChannel(item) + + # define info for trakt + try: + from core import trakt_tools + trakt_tools.set_trakt_info(item) + except: + pass + logger.debug('item.action=', item.action.upper()) + + # First checks if channel has a "play" function + if hasattr(channel, 'play'): + logger.debug('Executing channel "play" method') + itemlist = channel.play(item) + # Play should return a list of playable URLS + if len(itemlist) > 0 and isinstance(itemlist[0], Item): + item = itemlist[0] + platformtools.play_video(item) + + # Allow several qualities from Play in El Channel + elif len(itemlist) > 0 and isinstance(itemlist[0], list): + item.video_urls = itemlist + platformtools.play_video(item) + + # If not, shows user an error message + else: + platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339)) + + # If player don't have a "play" function, not uses the standard play from platformtools + else: + logger.debug('Executing core "play" method') + platformtools.play_video(item) + + +def findvideos(item, itemlist=[]): + if not itemlist: + logger.debug('Executing channel', item.channel, 'method', item.action) + channel = importChannel(item) + from core import servertools + p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683)) - p_dialog.update(0, '') - item.play_from = 'window' - itemlist = videolibrary.findvideos(item) - p_dialog.update(100, ''); sleep(0.5); p_dialog.close() - played = False + p_dialog.update(0) - # The number of links to show is limited - if config.get_setting("max_links", "videolibrary") != 0: itemlist = limit_itemlist(itemlist) - # The list of links is slightly "cleaned" - if config.get_setting("replace_VD", "videolibrary") == 1: itemlist = reorder_itemlist(itemlist) + try: + # First checks if channel has a "findvideos" function + if hasattr(channel, 'findvideos'): + itemlist = getattr(channel, item.action)(item) - if len(itemlist) > 0: - reopen = False + # If not, uses the generic findvideos function + else: + logger.debug('No channel "findvideos" method, executing core method') + itemlist = servertools.find_video_items(item) - while not xbmc.Monitor().abortRequested(): - played = True - # if config.get_setting('next_ep') == 3 and xbmc.Player().playnext: - # return - # The user chooses the mirror - if not platformtools.is_playing(): - if config.get_setting('next_ep') == 3: - xbmc.sleep(500) - if platformtools.is_playing(): - return - if config.get_setting('autoplay') or reopen: - played_time = get_played_time(item) - if not played_time and played: - return + itemlist = limitItemlist(itemlist) + except Exception as ex: + template = "An exception of type %s occured. Arguments:\n%r" + message = template % (type(ex).__name__, ex.args) + logger.error(" %s" % message) - options = [] - selection_implementation = 0 - for item in itemlist: - item.thumbnail = config.get_online_server_thumb(item.server) - quality = '[B][' + item.quality + '][/B]' if item.quality else '' - if item.server: - path = filetools.join(config.get_runtime_path(), 'servers', item.server.lower() + '.json') - name = jsontools.load(open(path, "rb").read())['name'] - if name.startswith('@'): name = config.get_localized_string(int(name.replace('@',''))) - logger.debug(item) - it = xbmcgui.ListItem('\n[B]%s[/B] %s - %s [%s]' % (name, quality, item.contentTitle, get_channel_parameters(item.contentChannel)['title'])) - it.setArt({'thumb':item.thumbnail}) - options.append(it) - else: - selection_implementation += 1 - # The selection window opens - if (item.contentSerieName and item.contentSeason and item.contentEpisodeNumber): head = ("%s - %sx%s | %s" % (item.contentSerieName, item.contentSeason, item.contentEpisodeNumber, config.get_localized_string(30163))) - else: head = config.get_localized_string(30163) - selection = platformtools.dialog_select(head, options, preselect= -1, useDetails=True) - if selection == -1: - return - else: - item = videolibrary.play(itemlist[selection + selection_implementation])[0] - platformtools.play_video(item) - reopen = True - if item.server == 'torrent': return - # if (platformtools.is_playing() and item.action) or item.server == 'torrent' or config.get_setting('autoplay'): break + p_dialog.update(100) + p_dialog.close() + serverlist = [s for s in itemlist if s.server] + if itemlist and not serverlist: + platformtools.render_items(itemlist, item) + if not serverlist: + platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60347)) + elif len(serverlist) == 1: + # If there is only one server play it immediately + play(itemlist[0].clone(no_return=True)) + else: + platformtools.serverWindow(item, itemlist) + + +def search(item): + channel = importChannel(item) + from core import channeltools + + if config.get_setting('last_search'): + last_search = channeltools.get_channel_setting('Last_searched', 'search', '') + else: + last_search = '' + + search_text = platformtools.dialog_input(last_search) + + if search_text is not None: + channeltools.set_channel_setting('Last_searched', search_text, 'search') + itemlist = new_search(item.clone(text=search_text), channel) + else: + return + + platformtools.render_items(itemlist, item) + + +def addToLibrary(item): + channel = importChannel(item) + from core import videolibrarytools + videolibrarytools.add_to_videolibrary(item, channel) + + +def importChannel(item): + channel = platformtools.channelImport(item.channel) + if not channel: + logger.debug('Channel', item.channel, 'not exist!') + return + + logger.debug('Running channel', channel.__name__, '|', channel.__file__) + return channel + + +def actions(item): + logger.debug('Executing channel', item.channel, 'method', item.action) + channel = importChannel(item) + itemlist = getattr(channel, item.action)(item) + if type(itemlist) == list: + if config.get_setting('trakt_sync'): + from core import trakt_tools + token_auth = config.get_setting('token_trakt', 'trakt') + if not token_auth: + trakt_tools.auth_trakt() + else: + import xbmc + if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting('install_trakt'): + trakt_tools.ask_install_script() + itemlist = trakt_tools.trakt_check(itemlist) + else: + config.set_setting('install_trakt', True) + + if item.action in ['check'] and len([s for s in itemlist if s.server]) > 0: + findvideos(item, itemlist) + else: + platformtools.render_items(itemlist, item) + + +def playFromLibrary(item): + if not item.next_ep: platformtools.fakeVideo() + item.action = item.next_action if item.next_action else 'findvideos' + logger.debug('Executing channel', item.channel, 'method', item.action) + return run(item) diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index 40245039..3c13354e 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -10,9 +10,12 @@ import sys if sys.version_info[0] >= 3: PY3 = True import urllib.parse as urllib + from concurrent import futures else: PY3 = False import urllib + from concurrent_py2 import futures + import os, xbmc, xbmcgui, xbmcplugin from past.utils import old_div @@ -310,47 +313,70 @@ def render_items(itemlist, parent_item): """ Function used to render itemlist on kodi """ + # if it's not a list, do nothing if not isinstance(itemlist, list): return - logger.debug('START render_items') + logger.debug('START renderItems') thumb_type = config.get_setting('video_thumbnail_type') from platformcode import shortcuts - # from core import httptools _handle = int(sys.argv[1]) default_fanart = config.get_fanart() def_context_commands = shortcuts.context() # if there's no item, add "no elements" item if not len(itemlist): - itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png'))) + from core.support import thumb + itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=thumb('nofolder'))) + + mode, Type = get_view_mode(itemlist[0], parent_item) + # from core.support import dbg;dbg() + if mode: + set_view_mode(sys.argv[2], mode) dirItems = [] - for n, item in enumerate(itemlist): - # item.itemlistPosition = n + 1 + + def setItem(n, item, parent_item): + item.itemlistPosition = n item_url = item.tourl() if item.category == "": item.category = parent_item.category - if not item.title: - item.title = '' # If there is no action or it is findvideos / play, folder = False because no listing will be returned - if item.action in ['play', '']: + if item.action in ['play', 'findvideos', '']: item.folder = False if item.fanart == "": item.fanart = parent_item.fanart - if item.action == 'play' and thumb_type == 1 and not item.forcethumb: - item.thumbnail = config.get_online_server_thumb(item.server) icon_image = "DefaultFolder.png" if item.folder else "DefaultVideo.png" - listitem = xbmcgui.ListItem(item.title) - listitem.setArt({'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail, - 'fanart': item.fanart if item.fanart else default_fanart}) + + title = item.title + + + listitem = xbmcgui.ListItem(title) + art = {'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail, 'fanart': item.fanart if item.fanart else default_fanart} + if item.infoLabels.get('landscape'): art['landscape'] = item.infoLabels['landscape'] + if item.infoLabels.get('clearlogo'): art['clearlogo'] = item.infoLabels['clearlogo'] + if item.infoLabels.get('clearart'): art['clearart'] = item.infoLabels['clearart'] + if item.infoLabels.get('banner'): art['banner'] = item.infoLabels['banner'] + if item.infoLabels.get('disc'): art['disc'] = item.infoLabels['disc'] + listitem.setProperty('ResumeTime', str(get_played_time(item))) + + listitem.setArt(art) if config.get_setting("player_mode") == 1 and item.action == "play" and not item.nfo: listitem.setProperty('IsPlayable', 'true') + if item.infoLabels.get('castandrole'): + try: + cast = [{'name':c[0], 'role':c[1], 'thumbnail':c[2], 'order':c[3]} for c in item.infoLabels.get("castandrole", [])] + cast.sort(key=lambda c: c['order']) + listitem.setCast(cast) + del item.infoLabels['castandrole'] + except: + pass + set_infolabels(listitem, item) # context menu @@ -359,12 +385,31 @@ def render_items(itemlist, parent_item): else: context_commands = def_context_commands listitem.addContextMenuItems(context_commands) + return item, item_url, listitem - dirItems.append(('%s?%s' % (sys.argv[0], item_url), listitem, item.folder)) + # For Debug + # from core.support import dbg;dbg() + # r_list = [setItem(i, item, parent_item) for i, item in enumerate(itemlist)] - set_view_mode(itemlist[0], parent_item) + r_list = [] + + with futures.ThreadPoolExecutor() as executor: + searchList = [executor.submit(setItem, 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(('{}?{}'.format(sys.argv[0], item_url), listitem, item.folder, len(r_list))) xbmcplugin.addDirectoryItems(_handle, dirItems) + if Type: xbmcplugin.setContent(handle=int(sys.argv[1]), content=Type) + + if parent_item.sorted: + if parent_item.sorted == 'year': xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE) + 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() else: @@ -378,40 +423,41 @@ def render_items(itemlist, parent_item): xbmcplugin.setPluginCategory(handle=_handle, category=breadcrumb) + xbmcplugin.endOfDirectory(_handle, succeeded=True, updateListing=False, cacheToDisc= True) # if parent_item.action in ['news', 'search', 'new_search', 'now_on_tv'] else False) + # if mode: + # xbmc.sleep(50) + # xbmc.executebuiltin('Container.SetViewMode(%s)' % mode) - # cacheToDisc = False - # if (parent_item.action == 'findvideos' and config.get_setting('autoplay')) or parent_item.action == 'search': - # cacheToDisc = True - - xbmcplugin.endOfDirectory(_handle, succeeded=True, updateListing=False, cacheToDisc=True) - logger.debug('END render_items') + from core import db; db.close() + logger.debug('END renderItems') def viewmodeMonitor(): - # logger.debug('WINDOW:',get_window()) + # logger.debug('WINDOW:',get_window(), xbmcgui.getCurrentWindowId()) if get_window() == 'WINDOW_VIDEO_NAV': try: - currentModeName = xbmc.getInfoLabel('Container.Viewmode') parent_info = xbmc.getInfoLabel('Container.FolderPath') - item_info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath') - win = xbmcgui.Window(10025) - currentMode = int(win.getFocusId()) - # logger.debug('CM', currentMode, 'CN',currentModeName, 'label',xbmc.getInfoLabel('Container.FolderPath')) - # if not parent_info: + if 'plugin.video.kod' in parent_info: + parent = Item().fromurl(parent_info, silent=True) + item = Item().fromurl(xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath'), silent=True) + currentModeName = xbmc.getInfoLabel('Container.Viewmode') + currentMode = int(xbmcgui.Window(10025).getFocusId()) + # logger.debug('SAVE VIEW 1', currentMode, parent.action, item.action) + if 50 <= currentMode < 520 and parent and parent.action != item.action: + content, Type = getCurrentView(item, parent) + view_mode_type = config.get_setting('view_mode_%s' % content) + # logger.debug('VIEW MODE TYPE') + if view_mode_type: + defaultMode = int(view_mode_type.split(',')[-1]) + if content and currentMode != defaultMode: + config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode)) + # logger.debug('SAVE VIEW 2', defaultMode, '->', currentMode) + if config.get_setting('viewchange_notify'): + dialog_notification(config.get_localized_string(70153), + config.get_localized_string(70187) % (content, currentModeName), + sound=False) - if currentModeName and 'plugin.video.kod' in parent_info and 50 <= currentMode < 1000:# and currentMode >= 50: # inside addon and in itemlist view - # logger.debug('CAMBIO VISUALE') - content, Type = getCurrentView(Item().fromurl(item_info) if item_info else Item(), Item().fromurl(parent_info)) - if content: - defaultMode = int(config.get_setting('view_mode_%s' % content).split(',')[-1]) - if currentMode != defaultMode: - # logger.debug('viewmode changed: ' + currentModeName + '-' + str(currentMode) + ' - content: ' + content) - config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode)) - if config.get_setting('viewchange_notify'): - dialog_notification(config.get_localized_string(70153), - config.get_localized_string(70187) % (content, currentModeName), - sound=False) except: import traceback logger.error(traceback.print_exc()) @@ -422,20 +468,9 @@ def getCurrentView(item=None, parent_item=None): if not item: item = Item() if not parent_item: - logger.debug('ESCO') + # logger.debug('ESCO') return None, None - # if not parent_item: - # info = xbmc.getInfoLabel('Container.FolderPath') - # if not info: - # return None, None - # parent_item = Item().fromurl(info) - # if not item: - # info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath') # first addon listitem (consider "..") - # if not info: - # item = Item() - # else: - # item = Item().fromurl(info) if info else Item() parent_actions = ['peliculas', 'novedades', 'search', 'get_from_temp', 'newest', 'discover_list', 'new_search', 'channel_search'] addons = 'addons' if config.get_setting('touch_view') else '' @@ -446,6 +481,9 @@ def getCurrentView(item=None, parent_item=None): elif parent_item.action == 'mainlist': return 'channel', addons + elif item.contentType == 'music': + return 'musicvideo', 'musicvideos' + elif (item.contentType in ['movie'] and parent_item.action in parent_actions) \ or (item.channel in ['videolibrary'] and parent_item.action in ['list_movies']) \ or (parent_item.channel in ['favorites'] and parent_item.action in ['mainlist']) \ @@ -460,11 +498,10 @@ def getCurrentView(item=None, parent_item=None): return 'episode', 'tvshows' elif parent_item.action in ['get_seasons']: - logger.debug('CONTENTTYPE:',item.contentType) return 'season', 'tvshows' elif parent_item.action in ['getmainlist', '', 'getchanneltypes']: - return 'home', addons + return None, None elif parent_item.action in ['filterchannels']: return 'channels', addons @@ -476,27 +513,84 @@ def getCurrentView(item=None, parent_item=None): return None, None - -def set_view_mode(item, parent_item): +def get_view_mode(item, parent_item): def reset_view_mode(): for mode in ['home','menu','channels','channel','movie','tvshow','season','episode','server']: config.set_setting('skin_name', xbmc.getSkinDir()) config.set_setting('view_mode_%s' % mode, config.get_localized_string(70003) + ' , 0') + content, Type = getCurrentView(item, parent_item) + if xbmc.getSkinDir() != config.get_setting('skin_name') or not config.get_setting('skin_name'): reset_view_mode() - xbmcplugin.setContent(handle=int(sys.argv[1]), content='') - xbmc.executebuiltin('Container.SetViewMode(%s)' % 55) + return 55, Type - content, Type = getCurrentView(item, parent_item) if content: mode = int(config.get_setting('view_mode_%s' % content).split(',')[-1]) if mode == 0: logger.debug('default mode') mode = 55 - xbmcplugin.setContent(handle=int(sys.argv[1]), content=Type) - xbmc.executebuiltin('Container.SetViewMode(%s)' % mode) - logger.debug('TYPE: ' + Type + ' - ' + 'CONTENT: ' + content) + return mode, Type + + return None, None + + +def set_view_mode(url, mode): + import re + find = re.findall('(%\d\w)', url, flags=re.DOTALL) + for f in find: + url = url.replace(f, f.lower()) + + def get_connection(): + from core import filetools + + file_db = "" + + # We look for the archive of the video database according to the version of kodi + view_db = config.get_platform(True)['view_db'] + if view_db: + file_db = filetools.join(xbmc.translatePath("special://userdata/Database"), view_db) + + # alternative method to locate the database + if not file_db or not filetools.exists(file_db): + file_db = "" + for f in filetools.listdir(xbmc.translatePath("special://userdata/Database")): + path_f = filetools.join(xbmc.translatePath("special://userdata/Database"), f) + + if filetools.isfile(path_f) and f.lower().startswith('viewmodes') and f.lower().endswith('.db'): + file_db = path_f + break + try: + import sqlite3 + return sqlite3.connect(file_db) + except: + return None + + def execute_sql(conn, sql): + cursor = conn.cursor() + cursor.execute(sql) + conn.commit() + + return cursor.fetchall() + + conn = get_connection() + if conn: + skin_name = config.get_skin() + try: + sql = 'select idView from view where (path="{}{}" and skin="{}")'.format(sys.argv[0], url, skin_name) + records = execute_sql(conn, sql) + if records: + # from core.support import dbg;dbg() + sql = 'update view set viewMode={} where idView={}'.format(mode, records[0][0]) + records = execute_sql(conn, sql) + else: + # from core.support import dbg;dbg() + sql = 'INSERT INTO view (window, path, viewMode, sortMethod, sortOrder, sortAttributes, skin) VALUES ' \ + '(10025, "{}{}", {}, 0, 1, 0, "{}")'.format(sys.argv[0], url, mode, skin_name) + records = execute_sql(conn, sql) + except: + pass + conn.close() def set_infolabels(listitem, item, player=False): @@ -511,33 +605,23 @@ def set_infolabels(listitem, item, player=False): @type item: item """ - infoLabels_dict = {'aired': 'aired', 'album': 'album', 'artist': 'artist', 'cast': 'cast', - 'castandrole': 'castandrole', 'tmdb_id': 'code', 'code': 'code', 'country': 'country', - 'credits': 'credits', 'release_date': 'dateadded', 'dateadded': 'dateadded', 'dbid': 'dbid', - 'director': 'director', 'duration': 'duration', 'episode': 'episode', - 'episodio_sinopsis': 'episodeguide', 'episodio_air_date': 'None', 'episodio_imagen': 'None', - 'episodio_titulo': 'title', 'episodio_vote_average': 'rating', 'episodio_vote_count': 'votes', - 'fanart': 'None', 'genre': 'genre', 'homepage': 'None', 'imdb_id': 'imdbnumber', - 'imdbnumber': 'imdbnumber', 'in_production': 'None', 'last_air_date': 'lastplayed', - 'mediatype': 'mediatype', 'mpaa': 'mpaa', 'number_of_episodes': 'None', - 'number_of_seasons': 'None', 'original_language': 'None', 'originaltitle': 'originaltitle', - 'overlay': 'overlay', 'poster_path': 'path', 'popularity': 'None', 'playcount': 'playcount', - 'plot': 'plot', 'plotoutline': 'plotoutline', 'premiered': 'premiered', 'quality': 'None', - 'rating': 'rating', 'season': 'season', 'set': 'set', 'setid': 'setid', - 'setoverview': 'setoverview', 'showlink': 'showlink', 'sortepisode': 'sortepisode', - 'sortseason': 'sortseason', 'sorttitle': 'sorttitle', 'status': 'status', 'studio': 'studio', - 'tag': 'tag', 'tagline': 'tagline', 'temporada_air_date': 'None', 'temporada_nombre': 'None', - 'temporada_num_episodios': 'None', 'temporada_poster': 'None', 'title': 'title', - 'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'thumbnail': 'None', - 'tvdb_id': 'None', 'tvshowtitle': 'tvshowtitle', 'type': 'None', 'userrating': 'userrating', - 'url_scraper': 'None', 'votes': 'votes', 'writer': 'writer', 'year': 'year'} + infoLabels_dict = {'aired': 'aired', 'album': 'album', 'artist': 'artist', 'cast': 'cast', 'castandrole': 'castandrole', + 'tmdb_id': 'code', 'code': 'code', 'country': 'country', 'credits': 'credits', 'release_date': 'dateadded', + 'dateadded': 'dateadded', 'dbid': 'dbid', 'director': 'director', 'duration': 'duration', 'episode': 'episode', + 'episode_plot': 'episodeguide', 'episode_title': 'title', 'episode_vote_average': 'rating', 'episode_vote_count': 'votes', + 'genre': 'genre', 'imdb_id': 'imdbnumber', 'imdbnumber': 'imdbnumber', 'last_air_date': 'lastplayed', 'mediatype': 'mediatype', + 'mpaa': 'mpaa', 'originaltitle': 'originaltitle', 'overlay': 'overlay', 'poster_path': 'path', 'playcount': 'playcount', + 'plot': 'plot', 'plotoutline': 'plotoutline', 'premiered': 'premiered', 'rating': 'rating', 'season': 'season', 'set': 'set', + 'setid': 'setid', 'setoverview': 'setoverview', 'showlink': 'showlink', 'sortepisode': 'sortepisode', 'sortseason': 'sortseason', + 'sorttitle': 'sorttitle', 'status': 'status', 'studio': 'studio', 'tag': 'tag', 'tagline': 'tagline', 'title': 'title', + 'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'tvshowtitle': 'tvshowtitle', 'userrating': 'userrating', + 'votes': 'votes', 'writer': 'writer', 'year': 'year'} # if item.infoLabels: try: - infoLabels_kodi = {infoLabels_dict[label_tag]: item.infoLabels[label_tag] for label_tag, label_value in list(item.infoLabels.items()) if infoLabels_dict[label_tag] != 'None'} + infoLabels_kodi = {infoLabels_dict[label_tag]: label_value for label_tag, label_value in list(item.infoLabels.items()) if label_tag in infoLabels_dict} listitem.setInfo("video", infoLabels_kodi) except: listitem.setInfo("video", item.infoLabels) - # logger.error(item.infoLabels) def set_context_commands(item, item_url, parent_item, **kwargs): @@ -605,39 +689,16 @@ def set_context_commands(item, item_url, parent_item, **kwargs): else: context_commands.append((command["title"], "RunPlugin(%s?%s)" % (sys.argv[0], item.clone(**command).tourl()))) # Do not add more predefined options if you are inside kodfavoritos - # if parent_item.channel == 'kodfavorites': - # return context_commands + if parent_item.channel == 'kodfavorites': + 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 # Options according to criteria, only if the item is not a tag, nor is it "Add to the video library", etc... if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer", "actualizar_titulos"]: # Show information: if the item has a plot, we assume that it is a series, season, chapter or movie # if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'): # context_commands.append((config.get_localized_string(60348), "Action(Info)")) - 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=' + item.action))) - # Add Movie to Video Library - elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle: - context_commands.append((config.get_localized_string(60353), "RunPlugin(%s?%s&%s)" % ( - sys.argv[0], item_url, 'action=add_pelicula_to_library&from_action=' + item.action))) - # Add to Video Library - elif item.action in ['check'] and item.contentTitle: - context_commands.append((config.get_localized_string(30161), "RunPlugin(%s?%s&%s)" % ( - sys.argv[0], item_url, 'action=add_to_library&from_action=' + item.action))) - - # Search trailer... - 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})))) - - # Add to kodfavoritos (My links) - if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "kodfavorites": - context_commands.append( (config.get_localized_string(70557), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "kodfavorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action})))) - # Add to kodfavoritos - if parent_item.channel == 'globalsearch': - context_commands.append( (config.get_localized_string(30155), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "favorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action})))) - # InfoPlus if config.get_setting("infoplus"): #if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \ @@ -645,8 +706,35 @@ def set_context_commands(item, item_url, parent_item, **kwargs): if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']: context_commands.append(("InfoPlus", "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=infoplus&action=Main&from_channel=' + item.channel))) - # Search in other channels - if item.contentTitle and item.contentType in ['movie', 'tvshow'] and parent_item.channel not in ['search', 'globalsearch'] and item.action not in ['play']: #and parent_item.action != 'mainlist': + 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=' + item.action))) + # Add Movie to Video Library + elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle: + context_commands.append((config.get_localized_string(60353), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_pelicula_to_library&from_action=' + item.action))) + # Add to Video Library + elif item.action in ['check'] and item.contentTitle: + context_commands.append((config.get_localized_string(30161), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_to_library&from_action=' + item.action))) + + # Search trailer... + 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})))) + + # Add to kodfavoritos (My links) + if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "favorites" and parent_item.from_channel != "kodfavorites": + context_commands.append( (config.get_localized_string(70557), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "kodfavorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action})))) + + # Add to kodfavoritos + if parent_item.channel == 'globalsearch': + context_commands.append( (config.get_localized_string(30155), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "favorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action})))) + + # Open in browser and previous menu + if parent_item.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist": + context_commands.append((config.get_localized_string(70739), "Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl()))) + + # Search in other channels + if item.contentTitle and item.contentType in ['movie', 'tvshow'] and parent_item.channel not in ['search', 'globalsearch'] and item.action not in ['play'] and parent_item.action != 'mainlist': # Search in other channels if item.contentSerieName != '': @@ -665,11 +753,6 @@ 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'])))) - - # Open in browser and previous menu - if parent_item.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist" and not parent_item.noMainMenu: - context_commands.append((config.get_localized_string(70739), "Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl()))) - 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": @@ -960,6 +1043,7 @@ def get_window(): def play_video(item, strm=False, force_direct=False, autoplay=False): + from core import httptools logger.debug() logger.debug(item.tostring('\n')) @@ -977,7 +1061,6 @@ def play_video(item, strm=False, force_direct=False, autoplay=False): # pass referer if item.referer: - from core import httptools httptools.default_headers['Referer'] = item.referer # Open the selection dialog to see the available options @@ -999,9 +1082,33 @@ def play_video(item, strm=False, force_direct=False, autoplay=False): # we get the selected video mediaurl, view, mpd, hls = get_video_seleccionado(item, seleccion, video_urls, autoplay) if not mediaurl: return + # to better disguise KoD as a browser + headers = {'User-Agent': httptools.get_user_agent(), 'Referer': item.referer if item.server == 'directo' else item.url} + # Kodi does not seems to allow this, leaving there as may work in the future + # if config.get_setting('resolver_dns'): + # try: + # import urllib.parse as urlparse + # except ImportError: + # import urlparse + # from lib import doh + # try: + # parse = urlparse.urlparse(mediaurl) + # if parse.netloc: + # domain = parse.netloc + # if not scrapertools.find_single_match(domain, '\d+\.\d+\.\d+\.\d+'): + # ip = doh.query(domain)[0] + # logger.info('Query DoH: ' + domain + ' = ' + str(ip)) + # parse = list(parse) + # parse[1] = ip + # mediaurl = urlparse.urlunparse(parse) + # headers['Host'] = domain + # except: + # logger.error('Failed to resolve hostname, fallback to normal dns') + if '|' not in mediaurl: + mediaurl = mediaurl + '|' + urllib.urlencode(headers) # video information is obtained. - xlistitem = xbmcgui.ListItem(path=item.url) + xlistitem = xbmcgui.ListItem(item.title, path=item.url) xlistitem.setArt({"thumb": item.contentThumbnail if item.contentThumbnail else item.thumbnail}) set_infolabels(xlistitem, item, True) @@ -1016,12 +1123,14 @@ 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') + xlistitem.setProperty('inputstream.adaptive.stream_headers', httptools.get_user_agent()) elif hls or 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') xlistitem.setProperty('inputstream.adaptive.manifest_type', 'hls') xlistitem.setMimeType('application/x-mpegURL') + xlistitem.setProperty('inputstream.adaptive.stream_headers', httptools.get_user_agent()) if force_direct: item.play_from = 'window' @@ -1368,7 +1477,10 @@ def get_video_seleccionado(item, seleccion, video_urls, autoplay=False): def set_player(item, xlistitem, mediaurl, view, strm): logger.debug() item.options = {'strm':False} - # logger.debug("item:\n" + item.tostring('\n')) + if item.subtitle: + if type(item.subtitle) != list: item.subtitle = [item.subtitle] + # item.subtitle.reverse() + xlistitem.setSubtitles(item.subtitle) # Moved del conector "torrent" here if item.server == "torrent": @@ -1377,9 +1489,6 @@ def set_player(item, xlistitem, mediaurl, view, strm): # If it is a strm file, play is not necessary elif strm: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xlistitem) - if item.subtitle: - xbmc.sleep(2000) - xbmc_player.setSubtitles(item.subtitle) else: if type(item.player_mode) == int: @@ -1389,11 +1498,10 @@ def set_player(item, xlistitem, mediaurl, view, strm): if (player_mode == 3 and mediaurl.startswith("rtmp")): player_mode = 0 elif "megacrypter.com" in mediaurl: player_mode = 3 logger.info("mediaurl=" + mediaurl) - + prevent_busy() if player_mode in [0,1]: - prevent_busy(item) if player_mode in [1]: - item.played_time = resume_playback(get_played_time(item)) + xlistitem.setProperty('StartOffset','{}'.format(resume_playback(get_played_time(item)))) logger.info('Player Mode:',['Direct', 'Bookmark'][player_mode]) # Add the listitem to a playlist @@ -1418,26 +1526,13 @@ def set_player(item, xlistitem, mediaurl, view, strm): download_and_play.download_and_play(mediaurl, "download_and_play.tmp", config.get_setting("downloadpath")) return - # ALL LOOKING TO REMOVE VIEW - if item.subtitle and view: - logger.info("External subtitles: " + item.subtitle) - xbmc.sleep(2000) - xbmc_player.setSubtitles(item.subtitle) - # if it is a video library file send to mark as seen if strm or item.strm_path: item.options['strm'] = True - # if player_mode == 1: item.options['continue'] = True + if not mediaurl.startswith('plugin'): from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_auto_as_watched(item) - # for cases where the audio playback window appears in place of the video one - if item.focusOnVideoPlayer: - while is_playing() and xbmcgui.getCurrentWindowId() != 12006: - continue - xbmc.sleep(500) - xbmcgui.Window(12005).show() - def add_next_to_playlist(item): import threading @@ -1451,7 +1546,7 @@ def add_next_to_playlist(item): nfo_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"), next.strm_path.replace('strm','nfo')) if nfo_path and filetools.isfile(nfo_path): head_nfo, item_nfo = videolibrarytools.read_nfo(nfo_path) - nextItem = xbmcgui.ListItem(path=item_nfo.url) + nextItem = xbmcgui.ListItem(item_nfo.fulltitle, path=item_nfo.url) nextItem.setArt({"thumb": item_nfo.contentThumbnail if item_nfo.contentThumbnail else item_nfo.thumbnail}) set_infolabels(nextItem, item_nfo, True) nexturl = "plugin://plugin.video.kod/?" + next.tourl() @@ -1495,7 +1590,7 @@ def play_torrent(item, xlistitem, mediaurl): selection = 0 if selection >= 0: - prevent_busy(item) + prevent_busy() mediaurl = urllib.quote_plus(item.url) torr_client = torrent_options[selection][0] @@ -1650,7 +1745,7 @@ def get_played_time(item): import traceback logger.error(traceback.format_exc()) del db['viewed'][ID] - + # db.close() return played_time @@ -1680,19 +1775,264 @@ def set_played_time(item): import traceback logger.error(traceback.format_exc()) del db['viewed'][ID] + db.close() + +def prevent_busy(): + xbmc.executebuiltin('Dialog.Close(all,true)') -def prevent_busy(item=None): - if item and (not item.autoplay and item.channel != 'videolibrary' and not item.window): - fakeVideo() - else: - xbmc.executebuiltin('Dialog.Close(all,true)') - - -def fakeVideo(): - xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, - xbmcgui.ListItem(path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4"))) - sleep = 200 +def fakeVideo(sleep = False): + mediaurl = os.path.join(config.get_runtime_path(), "resources", "kod.mp4") + xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=mediaurl)) while not is_playing(): - xbmc.sleep(sleep) + xbmc.sleep(200) xbmc.Player().stop() + + +def channelImport(channelId): + from core import filetools + ch = '' + path = filetools.join(config.get_runtime_path(), '{}', channelId + ".py") + if filetools.exists(path.format('channels')): ch = 'channels.{}'.format(channelId) + elif filetools.exists(path.format('specials')): ch = 'specials.{}'.format(channelId) + elif filetools.exists(path.format('platformcode')): ch = 'platformcode.{}'.format(channelId) + elif filetools.exists(path.format('core')): ch = 'core.{}'.format(channelId) + if ch: + channel = __import__(ch, None, None, [ch]) + else: + logger.info('Channel {} not Exist'.format(channelId)) + channel = None + return channel + +def serverWindow(item, itemlist): + from core import db + LEFT = 1 + RIGHT = 2 + UP = 3 + DOWN = 4 + ENTER = 7 + EXIT = 10 + BACKSPACE = 92 + + CONTEXT = 117 + + class ServerWindow(xbmcgui.WindowXMLDialog): + def start(self, item, itemlist): + prevent_busy() + self.itemlist = itemlist + self.item = item + self.servers = [] + items = [] + self.selection = -1 + self.actions = {} + for videoitem in self.itemlist: + videoitem.thumbnail = config.get_online_server_thumb(videoitem.server) + quality = ' [' + videoitem.quality + ']' if videoitem.quality else '' + info = ' [' + videoitem.extraInfo + ']' if videoitem.extraInfo else '' + if videoitem.server: + color = scrapertools.find_single_match(videoitem.alive, r'(FF[^\]]+)') + it = xbmcgui.ListItem('{}{}{}'.format(videoitem.serverName, quality, info)) + + # format Title + if videoitem.contentSeason and videoitem.contentEpisodeNumber: + title = '{}x{:02d}. {}'.format(videoitem.contentSeason, videoitem.contentEpisodeNumber, videoitem.contentTitle) + elif videoitem.contentEpisodeNumber: + title = '{:02d}. {}'.format(videoitem.contentEpisodeNumber, videoitem.contentTitle) + else: + title = videoitem.title + + it.setProperties({'name': title, 'channel': videoitem.ch_name, 'color': color if color else 'FF0082C2'}) + it.setArt({'poster':videoitem.contentThumbnail, 'thumb':videoitem.thumbnail, 'fanart':videoitem.contentFanart}) + self.servers.append(it) + items.append(videoitem) + else: + it = xbmcgui.ListItem(videoitem.title) + if 'library' in videoitem.action: + self.actions['videolibrary'] = videoitem + if 'download' in videoitem.action: + self.actions['download'] = videoitem + + self.itemlist = items + self.doModal() + return self.selection + + def onInit(self): + self.SERVERS = self.getControl(100) + self.VIDEOLIBRARY = self.getControl(103) + self.DOWNLOAD = self.getControl(104) + if 'videolibrary' not in self.actions.keys(): + self.VIDEOLIBRARY.setVisible(False) + if 'download' not in self.actions.keys(): + self.DOWNLOAD.setVisible(False) + self.SERVERS.reset() + self.SERVERS.addItems(self.servers) + self.setFocusId(100) + # from core.support import dbg;dbg() + + def onFocus(self, control): + if is_playing() and db['controls'].get('reopen', False): + self.close() + serverWindow(self.item, self.itemlist) + + def onAction(self, action): + action = action.getId() + focus = self.getFocusId() + if action in [UP, DOWN, LEFT, RIGHT] and focus not in [100, 101, 102, 103, 104]: + self.setFocusId(100) + elif action in [EXIT, BACKSPACE]: + self.close() + if action in [CONTEXT]: + context(self) + + def onClick(self, control): + if control == 100: + self.selection = self.itemlist[self.SERVERS.getSelectedPosition()].clone(window=True) + self.close() + elif control in [101]: + self.close() + elif control in [102]: + context(self) + elif control in [103]: + self.run(self.actions['videolibrary']) + elif control in [104]: + self.run(self.actions['download']) + + def run(self, action): + from platformcode.launcher import run + run(action) + + class ServerSkinWindow(xbmcgui.WindowXMLDialog): + def start(self, item, itemlist): + prevent_busy() + self.item = item + self.itemlist = itemlist + self.selection = -1 + self.actions = [] + self.doModal() + return self.selection + + def onInit(self): + try: + self.SERVERS = self.getControl(6) + self.exit = self.getControl(5) + self.exit.setNavigation(self.exit, self.exit, self.SERVERS, self.SERVERS) + except: + pass + + try: self.getControl(7).setVisible(False) + except: pass + try: self.getControl(8).setVisible(False) + except: pass + + self.exit.setLabel(config.get_localized_string(60396)) + + for item in itemlist: + if item.server: break + if item.contentSeason and item.contentEpisodeNumber: + title = '{}x{:02d}. {}'.format(item.contentSeason, item.contentEpisodeNumber, item.contentTitle) + elif item.contentEpisodeNumber: + title = '{:02d}. {}'.format(item.contentEpisodeNumber, item.contentTitle) + else: + title = item.fulltitle + + self.getControl(1).setLabel(title) + + items = [] + + from core.support import typo + for videoitem in self.itemlist: + if videoitem.server: + logger.debug(videoitem) + videoitem.thumbnail = config.get_online_server_thumb(videoitem.server) + quality = ' [' + videoitem.quality + ']' if videoitem.quality else '' + color = scrapertools.find_single_match(videoitem.alive, r'(FF[^\]]+)') + color = typo(' •', 'bold color 0x{}'.format(color)) if color else '' + info = ' [' + videoitem.extraInfo + ']' if videoitem.extraInfo else '' + title = '{}{}{}{}'.format(videoitem.serverName, quality, info, color) + else: + title = videoitem.title + it = xbmcgui.ListItem(title) + if videoitem.ch_name: + it.setLabel2(videoitem.ch_name) + elif not videoitem.action: + it.setLabel2(videoitem.plot) + else: + it.setLabel2(videoitem.fulltitle) + it.setArt({'thumb': videoitem.thumbnail}) + + items.append(it) + self.SERVERS.reset() + self.SERVERS.addItems(items) + self.setFocus(self.SERVERS) + + def onFocus(self, control): + if is_playing() and db['controls'].get('reopen', False): + self.close() + serverWindow(self.item, self.itemlist) + + def onAction(self, action): + action = action.getId() + if action in [CONTEXT]: + context(self) + if action in [EXIT, BACKSPACE]: + self.close() + + def onClick(self, control): + if control == 6: + self.selection = self.itemlist[self.SERVERS.getSelectedPosition()] + if not self.selection.action: + it = self.selection + self.selection = -1 + dialog_textviewer(it.title, it.plot) + else: + self.close() + if control == 5: + self.close() + elif control == 7: + from platformcode.launcher import run + run(self.actions[1]) + elif control == 8: + from platformcode.launcher import run + run(self.actions[0]) + + + def context(self): + pos = self.SERVERS.getSelectedPosition() + parent = self.item + item = self.itemlist[pos] + if not item.server: + return + commands = set_context_commands(item, item.tourl(), parent) + context = [c[0] for c in commands] + context_commands = [c[1].replace('Container.Refresh', 'RunPlugin').replace('Container.Update', 'RunPlugin') for c in commands] + index = xbmcgui.Dialog().contextmenu(context) + if index > 0: xbmc.executebuiltin(context_commands[index]) + + + if itemlist: + def monitor(itemlist): + reopen = False + while not xbmc.Monitor().abortRequested(): + if not is_playing(): + if reopen: + xbmc.sleep(200) + if not db['controls'].get('reopen', False): + break + if config.get_setting('window_type') == 0: + selection = ServerSkinWindow("DialogSelect.xml", config.get_runtime_path()).start(item, itemlist) + else: + selection = ServerWindow('Servers.xml', config.get_runtime_path()).start(item, itemlist) + + if selection == -1: + break + + else: + from platformcode.launcher import run + run(selection) + reopen = True + if not selection.server or selection.server == 'torrent': break + + db.close() + logger.debug('Server Window EXIT') + import threading + threading.Thread(target=monitor, args=[itemlist]).start() diff --git a/platformcode/xbmc_videolibrary.py b/platformcode/xbmc_videolibrary.py index cfff9235..ca43bfad 100644 --- a/platformcode/xbmc_videolibrary.py +++ b/platformcode/xbmc_videolibrary.py @@ -33,7 +33,6 @@ def mark_auto_as_watched(item): marked = False sync = False next_episode = None - show_server = True mark_time = 0 percentage = float(config.get_setting("watched_setting")) / 100 @@ -53,22 +52,18 @@ def mark_auto_as_watched(item): except: pass try: total_time = xbmc.Player().getTotalTime() except: pass - if item.played_time and xbmcgui.getCurrentWindowId() == 12005: - xbmc.Player().seekTime(item.played_time) - item.played_time = 0 # Fix for Slow Devices mark_time = total_time * percentage difference = total_time - actual_time # Mark as Watched - if actual_time > mark_time and not marked: + if mark_time and total_time > actual_time > mark_time and not marked: logger.info("Marked as Watched") item.playcount = 1 marked = True item.played_time = 0 platformtools.set_played_time(item) if item.options['strm'] : sync = True - show_server = False from specials import videolibrary videolibrary.mark_content_as_watched2(item) if not next_episode: @@ -86,9 +81,16 @@ def mark_auto_as_watched(item): break # if item.options['continue']: - if actual_time < mark_time and mark_time: + from core import db + if marked: + logger.debug('CLOSE') + item.played_time = 0 + db['controls']['reopen'] = False + else: + logger.debug('REOPEN') item.played_time = actual_time - else: item.played_time = 0 + db['controls']['reopen'] = True + db.close() platformtools.set_played_time(item) # Silent sync with Trakt @@ -97,23 +99,14 @@ def mark_auto_as_watched(item): while platformtools.is_playing(): xbmc.sleep(100) - if not show_server and item.play_from != 'window' and not item.no_return: - xbmc.sleep(700) - xbmc.executebuiltin('Action(ParentDir)') - xbmc.sleep(500) - if next_episode and next_episode.next_ep and config.get_setting('next_ep') < 3: from platformcode.launcher import run run(next_episode) - # db need to be closed when not used, it will cause freezes - from core import db - db.close() - # If it is configured to mark as seen if config.get_setting("mark_as_watched", "videolibrary"): threading.Thread(target=mark_as_watched_subThread, args=[item]).start() - + logger.debug('EXIT MONITOR') def sync_trakt_addon(path_folder): """ diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 794753ad..36d2a304 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -2605,12 +2605,12 @@ msgid "Links view" msgstr "" msgctxt "#60622" -msgid "Normal window" +msgid "Pop-up window" msgstr "" msgctxt "#60623" -msgid "Pop-up window" -msgstr "" +msgid "Fullscreen window" +msgstr " msgctxt "#60624" msgid " Maximum number of links to display" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index bf8b7ccf..5afa566a 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -2604,13 +2604,13 @@ msgid "Links view" msgstr "Visualizzazione collegamenti" msgctxt "#60622" -msgid "Normal window" -msgstr "Finestra normale" - -msgctxt "#60623" msgid "Pop-up window" msgstr "Finestra pop-up" +msgctxt "#60623" +msgid "Fullscreen window" +msgstr "Finestra a schermo intero" + msgctxt "#60624" msgid " Maximum number of links to display" msgstr " Numero massimo di link da visualizzare" diff --git a/resources/settings.xml b/resources/settings.xml index 6975de39..8ff4ad80 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -23,7 +23,7 @@ <setting id="autoplay" type="bool" label="70562" default="false" visible="true"/> <setting id="servers_favorites" visible="true" type="action" label="60551" action="RunPlugin(plugin://plugin.video.kod/?ew0KICAgICJhY3Rpb24iOiAic2VydmVyc19mYXZvcml0ZXMiLA0KICAgICJjaGFubmVsIjogInNldHRpbmciDQp9==)"/> <setting id="servers_blacklist" visible="true" type="action" label="60550" action="RunPlugin(plugin://plugin.video.kod/?ew0KICAgICJhY3Rpb24iOiAic2VydmVyc19ibGFja2xpc3QiLA0KICAgICJjaGFubmVsIjogInNldHRpbmciDQp9==)"/> - + <setting id="window_type" type="select" lvalues="60622|60623" label="60621" default="0"/> <!-- <setting id="hide_servers" type="bool" label="70747" default="false" visible="eq(-1,true)" subsetting="true"/> --> <setting id="checklinks" type="bool" label="30020" default="false"/> <setting id="checklinks_number" type="slider" option="int" range="5,5,20" label="30021" default="5" visible="eq(-1,true)" subsetting="true"/> @@ -92,6 +92,7 @@ <setting id="tmdb_active" default="true" visible="false"/> <!-- <setting id="tmdb_threads" type="slider" option="int" range="5,5,30" label="70155" default="20"/>--> <setting id="tmdb_plus_info" type="bool" label="70156" default="false"/> + <setting id="episode_info" type="bool" label="60292" default="false"/> <setting id="tmdb_cache" type="bool" label="70157" default="true"/> <setting id="tmdb_cache_expire" type="select" lvalues="70158|70159|70160|70161|70170" label="70162" enable="eq(-1,true)" default="4"/> <setting id="tmdb_clean_db_cache" type="action" label="70163" action="RunPlugin(plugin://plugin.video.kod/?ew0KICAgICJhY3Rpb24iOiAic2NyaXB0Ig0KfQ==)" /> @@ -136,7 +137,7 @@ <setting id="enable_library_menu" label="30131" type="bool" default="true"/> <setting label="30000" type="lsep"/> <setting id="touch_view" label='30002' type="bool" default="false"/> - <setting id="viewchange_notify" label='70514' type="bool" default="true"/> + <setting id="viewchange_notify" label='70514' type="bool" default="false"/> <!-- View Mode (hidden)--> <setting id="skin_name" label='Skin Name' type="text" default="skin.estuary" visible="false"/> <setting id="view_mode_home" type="action" label="70009" default= "Default, 0" visible="false"/> @@ -148,6 +149,7 @@ <setting id="view_mode_season" type="action" label="30140" default= "Default, 0" visible="false"/> <setting id="view_mode_episode" type="action" label="70362" default= "Default, 0" visible="false"/> <setting id="view_mode_server" type="action" label="70145" default= "Default, 0" visible="false"/> + <setting id="view_mode_musicvideo" type="action" label="70145" default= "Default, 0" visible="false"/> <!-- Contextual --> <setting label="30024" type="lsep"/> <setting id="quick_menu" type="bool" label="60360" default="true"/> diff --git a/resources/skins/Default/720p/Servers.xml b/resources/skins/Default/720p/Servers.xml new file mode 100644 index 00000000..61d44051 --- /dev/null +++ b/resources/skins/Default/720p/Servers.xml @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<window> + <zorder>0.52</zorder> + <coordinates> + <left>0</left> + <top>0</top> + </coordinates> + <controls> + <control type="group"> + <description>Servers Group</description> + <animation type="WindowOpen" reversible="false"> + <effect type="fade" delay="160" end="100" time="200" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="fade" delay="300" start="100" end="0" time="200" /> + </animation> + <control type="image"> + <description>Window Background</description> + <width>100%</width> + <height>100%</height> + <texture colordiffuse="FF232323">white.png</texture> + </control> + <control type="image"> + <description>Fanart</description> + <width>100%</width> + <height>100%</height> + <aspectratio>scale</aspectratio> + <texture colordiffuse="FF555555">$INFO[Container(100).ListItem.Art(fanart)]</texture> + </control> + <control type="image"> + <description>Poster</description> + <top>0</top> + <left>0</left> + <width>480</width> + <height>720</height> + <texture>$INFO[Container(100).ListItem.Art(poster)]</texture> + <animation type="WindowOpen" reversible="false"> + <effect type="slide" delay="160" start="-100,0" end="0,0" time="200" /> + <effect type="fade" delay="160" start="0" end="100" time="200" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="slide" delay="160" start="0,0" end="-100,0" time="200" /> + <effect type="fade" delay="160" start="100" end="0" time="200" /> + </animation> + </control> + <control type="textbox"> + <description>Main Title</description> + <left>520</left> + <top>40</top> + <width>1150</width> + <height>30</height> + <font>font13</font> + <textcolor>FFFFFFFF</textcolor> + <shadowcolor>00000000</shadowcolor> + <align>left</align> + <aligny>center</aligny> + <label>$INFO[Container(100).ListItem.Property(name)]</label> + <animation type="WindowOpen" reversible="false"> + <effect type="slide" delay="160" start="0,-70" end="0,0" time="200" /> + <effect type="fade" delay="160" start="0" end="100" time="200" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="slide" delay="160" start="0,0" end="0,-70" time="200" /> + <effect type="fade" delay="160" start="100" end="0" time="200" /> + </animation> + </control> + <control type="list" id="100"> + <description>Servers List</description> + <bottom>40</bottom> + <left>520</left> + <width>700</width> + <height>570</height> + <onup>101</onup> + <onleft>101</onleft> + <onright>101</onright> + <animation type="WindowOpen" reversible="false"> + <effect type="slide" delay="160" start="100,0" end="0,0" time="200" /> + <effect type="fade" delay="160" start="0" end="100" time="200" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="slide" delay="160" start="0,0" end="100,0" time="200" /> + <effect type="fade" delay="160" start="100" end="0" time="200" /> + </animation> + <scrolltime tween="cubic" easing="out">300</scrolltime> + <itemlayout height="140" width="700"> + <control type="image"> + <description>Servers Icon</description> + <top>5</top> + <left>5</left> + <width>120</width> + <height>120</height> + <texture>$INFO[ListItem.Art(thumb)]</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="textbox"> + <description>Server Title</description> + <left>150</left> + <top>30</top> + <width>450</width> + <height>30</height> + <font>font13</font> + <textcolor>FFFFFFFF</textcolor> + <shadowcolor>00000000</shadowcolor> + <align>left</align> + <aligny>center</aligny> + <label>[B]$INFO[ListItem.Label][/B]</label> + </control> + <control type="textbox"> + <description>Channel</description> + <left>150</left> + <top>65</top> + <width>450</width> + <height>30</height> + <font>font13</font> + <textcolor>FFAAAAAA</textcolor> + <shadowcolor>00000000</shadowcolor> + <align>left</align> + <aligny>center</aligny> + <label>[B]$INFO[ListItem.Property(channel)][/B]</label> + </control> + </itemlayout> + <focusedlayout height="140" width="700"> + <control type="image"> + <description>Selection Background</description> + <width>700</width> + <height>130</height> + <texture colordiffuse="CCFFFFFF">white.png</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="image"> + <description>Servers Color</description> + <top>0</top> + <left>0</left> + <width>130</width> + <height>130</height> + <texture colordiffuse="$INFO[ListItem.Property(color)]">white.png</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="image"> + <description>Servers Icon</description> + <top>5</top> + <left>5</left> + <width>120</width> + <height>120</height> + <texture>$INFO[ListItem.Art(thumb)]</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="textbox"> + <description>Server Title</description> + <left>150</left> + <top>30</top> + <width>450</width> + <height>30</height> + <font>font13</font> + <textcolor>FF232323</textcolor> + <shadowcolor>00000000</shadowcolor> + <align>left</align> + <aligny>center</aligny> + <label>[B]$INFO[ListItem.Label][/B]</label> + </control> + <control type="textbox"> + <description>Channel</description> + <left>150</left> + <top>65</top> + <width>450</width> + <height>30</height> + <font>font13</font> + <textcolor>FF555555</textcolor> + <shadowcolor>00000000</shadowcolor> + <align>left</align> + <aligny>center</aligny> + <label>[B]$INFO[ListItem.Property(channel)][/B]</label> + </control> + </focusedlayout> + </control> + <!-- END Servers List --> + <control type="group"> + <top>30</top> + <right>30</right> + <animation type="WindowOpen" reversible="false"> + <effect type="slide" delay="160" start="0,-70" end="0,0" time="200" /> + <effect type="fade" delay="160" start="0" end="100" time="200" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="slide" delay="160" start="0,0" end="0,-70" time="200" /> + <effect type="fade" delay="160" start="100" end="0" time="200" /> + </animation> + <control type="button" id="101"> + <description>Close</description> + <top>0</top> + <right>0</right> + <height>40</height> + <width>40</width> + <onup>100</onup> + <ondown>100</ondown> + <onleft condition="Control.IsVisible(102)">102</onleft> + <onleft condition="Control.IsVisible(103)">103</onleft> + <onleft>100</onleft> + <onright>100</onright> + <texturefocus colordiffuse="FFFFFFFF">close.png</texturefocus> + <texturenofocus colordiffuse="80FFFFFF">close.png</texturenofocus> + <!-- <onclick>Action(close)</onclick> --> + </control> + <control type="button" id="102"> + <description>Menu</description> + <top>0</top> + <right>40</right> + <height>40</height> + <width>40</width> + <onup>100</onup> + <ondown>100</ondown> + <onleft condition="Control.IsVisible(103)">103</onleft> + <onleft condition="!Control.IsVisible(103) + Control.IsVisible(104)">104</onleft> + <onleft>100</onleft> + <onright>101</onright> + <texturefocus colordiffuse="FFFFFFFF">menu.png</texturefocus> + <texturenofocus colordiffuse="80FFFFFF">menu.png</texturenofocus> + </control> + <control type="button" id="103"> + <description>videolibrary</description> + <top>0</top> + <right>80</right> + <height>40</height> + <width>40</width> + <onup>100</onup> + <ondown>100</ondown> + <onleft condition="Control.IsVisible(104)">104</onleft> + <onleft condition="!Control.IsVisible(104)">100</onleft> + <onright>102</onright> + <texturefocus colordiffuse="FFFFFFFF">add.png</texturefocus> + <texturenofocus colordiffuse="80FFFFFF">add.png</texturenofocus> + </control> + <control type="button" id="104"> + <description>Download</description> + <top>0</top> + <right>80</right> + <animation effect="slide" end="-40,0" condition="Control.IsVisible(103)">Conditional</animation> + <height>40</height> + <width>40</width> + <onup>100</onup> + <ondown>100</ondown> + <onleft>100</onleft> + <onright condition="Control.IsVisible(103)">102</onright> + <onright>102</onright> + <texturefocus colordiffuse="FFFFFFFF">down.png</texturefocus> + <texturenofocus colordiffuse="80FFFFFF">down.png</texturenofocus> + </control> + </control> + </control> + <!-- END SERVERS GROUP --> + </controls> +</window> \ No newline at end of file diff --git a/servers/dailymotion.py b/servers/dailymotion.py index 9242658c..070e3048 100644 --- a/servers/dailymotion.py +++ b/servers/dailymotion.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from core import httptools +from core import httptools, support from platformcode import logger, config @@ -19,8 +19,13 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("(page_url='%s')" % page_url) + video_urls = [] data = response.json url = data.get('qualities', {}).get('auto', [{}])[0].get('url','') - return [["m3u8 [dailymotion]", url]] \ No newline at end of file + urls = support.match(url, patron=r'NAME="([^"]+)"\s*,\s*PROGRESSIVE-URI="([^"]+)').matches + for quality, uri in urls: + video_urls.append(["mp4 [{}p] [dailymotion]".format(quality), uri]) + + return video_urls \ No newline at end of file diff --git a/servers/deltabit.py b/servers/deltabit.py index b217ae0e..a3cb1f40 100644 --- a/servers/deltabit.py +++ b/servers/deltabit.py @@ -14,7 +14,7 @@ def test_video_exists(page_url): data = page.data.replace('"', "'") real_url = page.url - if "Not Found" in data or "File Does not Exist" in data: + if "Not Found" in data or "File Does not Exist" in data or "File doesn't exits" in data: return False, config.get_localized_string(70449) % "DeltaBit" return True, "" diff --git a/servers/directo.py b/servers/directo.py index 2ad2e56b..8fafb732 100644 --- a/servers/directo.py +++ b/servers/directo.py @@ -10,6 +10,6 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.debug("(page_url='%s')" % page_url) - video_urls = [["%s %s" % (page_url[-4:], config.get_localized_string(30137)), page_url]] + video_urls = [["%s %s" % (page_url.split('|')[0][-4:], config.get_localized_string(30137)), page_url]] return video_urls diff --git a/servers/rapidgator.json b/servers/rapidgator.json deleted file mode 100644 index f3288ce4..00000000 --- a/servers/rapidgator.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "active": true, - "find_videos": { - "ignore_urls": [], - "patterns": [ - { - "pattern": "(rapidgator.net/file/\\w+(?:\\.html|))", - "url": "http://\\1" - } - ] - }, - "free": false, - "id": "rapidgator", - "name": "Rapid Gator", - "premium": [ - "realdebrid", - "alldebrid" - ], - "settings": [ - { - "default": false, - "enabled": true, - "id": "black_list", - "label": "@70708", - "type": "bool", - "visible": true - } - ] -} diff --git a/servers/rapidgator.py b/servers/rapidgator.py deleted file mode 100644 index fdc262e3..00000000 --- a/servers/rapidgator.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- - -from platformcode import logger - - -def test_video_exists(page_url): - return True, "" - - -def get_video_url(page_url, premium=False, user="", password="", video_password=""): - logger.debug("(page_url='%s')" % page_url) - video_urls = [] - return video_urls diff --git a/servers/streamsb.json b/servers/streamsb.json index e1d2783d..195264b5 100644 --- a/servers/streamsb.json +++ b/servers/streamsb.json @@ -4,12 +4,12 @@ "ignore_urls": [], "patterns": [ { - "pattern": "(?:streamsb|sbembed|sbembed1|sbplay1|sbplay|pelistop|tubesb|playersb|embedsb|watchsb).\\w{2,4}/(?:embed-|d/|e/)?([A-z0-9]+)", - "url": "https://streamsb.net/\\1" + "pattern": "(?:streamsb|sbembed|sbembed1|sbplay1|sbplay|pelistop|tubesb|playersb|embedsb|watchsb|streamas).\\w{2,5}/(?:embed-|d/|e/)?([A-z0-9]+)", + "url": "https://streamsb.net/d/\\1" }, { "pattern": "(?:cloudemb.com)/([A-z0-9]+)", - "url": "https://streamsb.net/\\1" + "url": "https://streamsb.net/d/\\1" } ] }, diff --git a/servers/streamsb.py b/servers/streamsb.py index 63592615..9ee2c514 100644 --- a/servers/streamsb.py +++ b/servers/streamsb.py @@ -2,10 +2,8 @@ # https://github.com/tvaddonsco/script.module.urlresolver/blob/master/lib/urlresolver/plugins/streamsb.py from core import httptools, scrapertools -from platformcode import config, logger -import time - -host = 'streamsb.net' +from platformcode import config +import base64 def test_video_exists(page_url): @@ -21,8 +19,8 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): video_urls = [] global data + host = scrapertools.get_domain_from_url(page_url) sources = scrapertools.find_multiple_matches(data, r'download_video([^"]+)[^\d]+\d+x(\d+)') - time.sleep(1) if sources: sources.sort(key=lambda x: int(x[1]), reverse=True) sources = [(x[1] + 'p', x[0]) for x in sources] @@ -30,9 +28,14 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= code, mode, hash = eval(s[1]) dl_url = 'https://{0}/dl?op=download_orig&id={1}&mode={2}&hash={3}'.format(host, code, mode, hash) data = httptools.downloadpage(dl_url).data - media_url = scrapertools.find_single_match(data, 'href="([^"]+)">Direct') - if media_url: - video_urls.append([s[0], media_url]) + + captcha = scrapertools.girc(data, 'https://{0}/'.format(host), base64.b64encode('https://{0}:443'.format(host).encode('utf-8')).decode('utf-8').replace('=', '')) + if captcha: + data = httptools.downloadpage(dl_url, post={'op': 'download_orig', 'id': code, 'mode': mode, + 'hash': hash, 'g-recaptcha-response': captcha}, timeout=10).data + media_url = scrapertools.find_single_match(data, 'href="([^"]+)">Direct') + if media_url: + video_urls.append([s[0], media_url]) return video_urls diff --git a/servers/torrent.json b/servers/torrent.json index 2124724b..3b2cd4d7 100644 --- a/servers/torrent.json +++ b/servers/torrent.json @@ -41,7 +41,7 @@ "ignore_urls": [], "patterns": [ { - "pattern": "(http:\\/\\/(?:[a-zA-Z0-9]+)\\.torrent)", + "pattern": "(https?:\/\/\\S+.torrent)", "url": "\\1" }, { @@ -49,7 +49,7 @@ "url": "\\1" }, { - "pattern": "(http://tumejorjuego.com/descargar/index.php\\?link=[^\"]+)", + "pattern": "(http[s]?://tumejorjuego.com/descargar/index.php\\?link=[^\"]+)", "url": "\\1" } ] diff --git a/servers/torrent.py b/servers/torrent.py index 672b03e5..4a7584ef 100755 --- a/servers/torrent.py +++ b/servers/torrent.py @@ -219,8 +219,11 @@ def find_file(hash): def elementum_actions(parameter, TorrentHash): elementum_setting, elementum_host, TorrentPath = setting() if elementum_setting: - if parameter == 'delete': monitor_update(TorrentPath, TorrentHash, remove=True) - requests.get('%s/%s/%s' %(elementum_host, parameter, TorrentHash)) + try: + if parameter == 'delete': monitor_update(TorrentPath, TorrentHash, remove=True) + requests.get('%s/%s/%s' %(elementum_host, parameter, TorrentHash)) + except: + pass def process_filename(filename, Title, ext=True): diff --git a/servers/uqload.py b/servers/uqload.py index 46ec18ce..d92dd590 100644 --- a/servers/uqload.py +++ b/servers/uqload.py @@ -30,7 +30,7 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= matches = re.compile(patron, re.DOTALL).findall(data) for url in matches: - url = url+'|Referer='+page_url + # url = url+'|Referer='+page_url video_urls.append(["[uqload]", url]) return video_urls diff --git a/service.py b/service.py index ce7332c0..52895c4f 100644 --- a/service.py +++ b/service.py @@ -513,8 +513,8 @@ if __name__ == "__main__": # scan new info xbmc.executebuiltin('UpdateLibrary(video)') xbmc.executebuiltin('CleanLibrary(video)') - while xbmc.getCondVisibility('Library.IsScanningVideo()'): - xbmc.sleep(1000) + # while xbmc.getCondVisibility('Library.IsScanningVideo()'): + # xbmc.sleep(1000) # check if the user has any connection problems from platformcode.checkhost import test_conn @@ -546,8 +546,12 @@ if __name__ == "__main__": logger.debug(threading.enumerate()) break - if monitor.waitForAbort(1): # every second + if monitor.waitForAbort(1): # every second + logger.debug('KoD service EXIT') # db need to be closed when not used, it will cause freezes - db.close() join_threads() + logger.debug('Close Threads') + db.close() + logger.debug('Close DB') break + logger.debug('KoD service STOPPED') \ No newline at end of file diff --git a/specials/community.py b/specials/community.py index 0856b142..a5ba8d5a 100644 --- a/specials/community.py +++ b/specials/community.py @@ -238,7 +238,7 @@ def peliculas(item, json='', key='', itemlist=[]): itemlist += itlist if item.sort: - itemlist.sort(key=lambda x: x.title, reverse=False) + itemlist.sort(key=lambda x: x.title.lower(), reverse=False) if Pagination and len(itemlist) >= Pagination: if inspect.stack()[1][3] != 'get_newest': item.title = support.typo(config.get_localized_string(30992), 'color kod bold') @@ -286,9 +286,9 @@ def get_seasons(item): 'get_newest'] and defp and not item.disable_pagination: itemlist = pagination(item, itemlist) - if show_seasons: - support.videolibrary(itemlist, item) - support.download(itemlist, item) + # if show_seasons: + support.videolibrary(itemlist, item) + support.download(itemlist, item) return itemlist @@ -393,6 +393,9 @@ def episodios(item, json='', key='', itemlist=[]): filterseason=str(season), path=item.path)) + support.videolibrary(itemlist, item) + support.download(itemlist, item) + elif defp and inspect.stack()[1][3] not in ['get_seasons'] and not item.disable_pagination: if Pagination and len(itemlist) >= Pagination: if inspect.stack()[1][3] != 'get_newest': @@ -400,9 +403,10 @@ def episodios(item, json='', key='', itemlist=[]): item.page = pag + 1 item.thumbnail = support.thumb() itemlist.append(item) - if not show_seasons: + + if inspect.stack()[1][3] not in ['get_seasons'] and not show_seasons: support.videolibrary(itemlist, item) - support.download(itemlist, item) + support.download(itemlist, item) return itemlist diff --git a/specials/globalsearch.py b/specials/globalsearch.py index cd17612a..c3b6878a 100644 --- a/specials/globalsearch.py +++ b/specials/globalsearch.py @@ -138,7 +138,7 @@ class SearchWindow(xbmcgui.WindowXML): module = __import__('channels.%s' % channel, fromlist=["channels.%s" % channel]) mainlist = getattr(module, 'mainlist')(Item(channel=channel, global_search=True)) action = [elem for elem in mainlist if elem.action == "search" and ( - self.item.mode in ['all', 'person'] or elem.contentType in [self.item.mode, 'undefined'])] + self.item.mode in ['all', 'person'] or elem.contentType in [self.item.type, 'undefined'])] self.moduleDict[channel] = module self.searchActions += action except: @@ -343,11 +343,11 @@ class SearchWindow(xbmcgui.WindowXML): for searchAction in self.getActions(): if self.exit: break self.search_threads.append(executor.submit(self.get_channel_results, searchAction)) - # for res in futures.as_completed(self.search_threads): - # if self.exit: break - # if res.result(): - # channel, valid, results = res.result() - # self.update(channel, valid, results) + for res in futures.as_completed(self.search_threads): + if self.exit: break + if res.result(): + channel, valid, results = res.result() + self.update(channel, valid, results) # if results: # name = results[0].channel @@ -363,7 +363,7 @@ class SearchWindow(xbmcgui.WindowXML): self.count = len(self.searchActions) def get_channel_results(self, searchAction): - def search(text): + def channel_search(text): valid = [] other = [] results = self.moduleDict[channel].search(searchAction, text) @@ -388,7 +388,7 @@ class SearchWindow(xbmcgui.WindowXML): other = [] try: - results, valid, other = search(self.item.text) + results, valid, other = channel_search(self.item.text) if self.exit: return # if we are on movie search but no valid results is found, and there's a lot of results (more pages), try @@ -396,7 +396,7 @@ class SearchWindow(xbmcgui.WindowXML): if self.item.contentType == 'movie' and not valid and other and other[-1].nextPage \ and self.item.infoLabels['year']: logger.debug('retring adding year on channel ' + channel) - dummy, valid, dummy = search(self.item.text + " " + str(self.item.infoLabels['year'])) + dummy, valid, dummy = channel_search(self.item.text + " " + str(self.item.infoLabels['year'])) if self.exit: return # some channels may use original title @@ -404,17 +404,18 @@ class SearchWindow(xbmcgui.WindowXML): original = scrapertools.title_unify(self.item.infoLabels.get('originaltitle')) if self.item.text != original: logger.debug('retring with original title on channel ' + channel) - dummy, valid, dummy = search(original) + dummy, valid, dummy = channel_search(original) except: import traceback logger.error(traceback.format_exc()) if self.exit: return - update_lock.acquire() + # update_lock.acquire() self.count += 1 - # return channel, valid, other if other else results + + return channel, valid, other if other else results self.update(channel, valid, other if other else results) - update_lock.release() + # update_lock.release() def makeItem(self, url): item = Item().fromurl(url) @@ -676,7 +677,7 @@ class SearchWindow(xbmcgui.WindowXML): busy(False) return - if item.action in ['add_pelicula_to_library', 'add_serie_to_library','save_download']: # special items (add to videolibrary, download ecc.) + if item.action: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item_url + ")") busy(False) return @@ -684,85 +685,32 @@ class SearchWindow(xbmcgui.WindowXML): try: self.channel = __import__('channels.%s' % item.channel, fromlist=["channels.%s" % item.channel]) self.itemsResult = getattr(self.channel, item.action)(item) + if self.itemsResult and self.itemsResult[0].server: + from platformcode.launcher import findvideos + findvideos(self.item, self.itemsResult) + return except: import traceback logger.error('error importing/getting search items of ' + item.channel) logger.error(traceback.format_exc()) self.itemsResult = [] - if self.itemsResult and self.itemsResult[0].action in ['play', '']: + self.episodes = self.itemsResult if self.itemsResult else [] + self.itemsResult = [] + ep = [] + for item in self.episodes: + it = xbmcgui.ListItem(item.title) + it.setProperty('item', item.tourl()) + ep.append(it) - if config.get_setting('checklinks') and not config.get_setting('autoplay'): - self.itemsResult = servertools.check_list_links(self.itemsResult, config.get_setting('checklinks_number')) - servers = self.itemsResult if self.itemsResult else [] - self.itemsResult = [] - uhd = [] - fhd = [] - hd = [] - sd = [] - unknown = [] - other = [] - for i, item in enumerate(servers): - if item.server: - it = self.makeItem(item.tourl()) - it.setProperty('index', str(i)) - if item.quality.lower() in ['4k', '2160p', '2160', '4k2160p', '4k2160', '4k 2160p', '4k 2160', '2k']: - it.setProperty('quality', 'uhd.png') - uhd.append(it) - elif item.quality.lower() in ['fullhd', 'fullhd 1080', 'fullhd 1080p', 'full hd', 'full hd 1080', 'full hd 1080p', 'hd1080', 'hd1080p', 'hd 1080', 'hd 1080p', '1080', '1080p']: - it.setProperty('quality', 'Fhd.png') - fhd.append(it) - elif item.quality.lower() in ['hd', 'hd720', 'hd720p', 'hd 720', 'hd 720p', '720', '720p', 'hdtv']: - it.setProperty('quality', 'hd.png') - hd.append(it) - elif item.quality.lower() in ['sd', '480p', '480', '360p', '360', '240p', '240']: - it.setProperty('quality', 'sd.png') - sd.append(it) - else: - it.setProperty('quality', '') - unknown.append(it) - elif not item.action: - self.getControl(QUALITYTAG).setText(item.fulltitle) - else: - it = self.makeItem(item.tourl()) - other.append(it) + if not ep: + ep = [xbmcgui.ListItem(config.get_localized_string(60347))] + ep[0].setProperty('thumb', channelselector.get_thumb('nofolder.png')) - uhd.sort(key=lambda it: it.getProperty('index')) - fhd.sort(key=lambda it: it.getProperty('index')) - hd.sort(key=lambda it: it.getProperty('index')) - sd.sort(key=lambda it: it.getProperty('index')) - unknown.sort(key=lambda it: it.getProperty('index')) - - serverlist = uhd + fhd + hd + sd + unknown + other - if not serverlist: - serverlist = [xbmcgui.ListItem(config.get_localized_string(60347))] - serverlist[0].setProperty('thumb', channelselector.get_thumb('nofolder.png')) - - self.Focus(SERVERS) - self.SERVERLIST.reset() - self.SERVERLIST.addItems(serverlist) - self.setFocusId(SERVERLIST) - - if config.get_setting('autoplay'): - busy(False) - - else: - self.episodes = self.itemsResult if self.itemsResult else [] - self.itemsResult = [] - ep = [] - for item in self.episodes: - it = xbmcgui.ListItem(item.title) - it.setProperty('item', item.tourl()) - ep.append(it) - - if not ep: - ep = [xbmcgui.ListItem(config.get_localized_string(60347))] - ep[0].setProperty('thumb', channelselector.get_thumb('nofolder.png')) - - self.Focus(EPISODES) - self.EPISODESLIST.reset() - self.EPISODESLIST.addItems(ep) - self.setFocusId(EPISODESLIST) + self.Focus(EPISODES) + self.EPISODESLIST.reset() + self.EPISODESLIST.addItems(ep) + self.setFocusId(EPISODESLIST) busy(False) diff --git a/specials/kodfavorites.py b/specials/kodfavorites.py index cc7f7fdf..f3fe0e8e 100644 --- a/specials/kodfavorites.py +++ b/specials/kodfavorites.py @@ -17,6 +17,8 @@ # from builtins import str import sys + +from lib import requests PY3 = False if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int from builtins import object @@ -158,9 +160,9 @@ def addFavourite(item): return False # If it is a movie / series, fill in tmdb information if tmdb_plus_info is not activated (for season / episode it is not necessary because the "second pass" will have already been done) - if (item.contentType == 'movie' or item.contentType == 'tvshow') and not config.get_setting('tmdb_plus_info', default=False): - from core import tmdb - tmdb.set_infoLabels(item, True) # get more data in "second pass" (actors, duration, ...) + # if (item.contentType == 'movie' or item.contentType == 'tvshow') and not config.get_setting('tmdb_plus_info', default=False): + # from core import tmdb + # tmdb.set_infoLabels(item, True) # get more data in "second pass" (actors, duration, ...) # Add date saved item.date_added = fechahora_actual() @@ -224,6 +226,7 @@ def mostrar_perfil(item): for i_enlace, enlace in enumerate(alfav.user_favorites[i_perfil]['items']): it = Item().fromurl(enlace) + it.from_channel = 'kodfavorites' it.context = [ {'title': config.get_localized_string(70617), 'channel': item.channel, 'action': 'acciones_enlace', 'i_enlace': i_enlace, 'i_perfil': i_perfil} ] @@ -232,16 +235,20 @@ def mostrar_perfil(item): it.plot += '[CR]Url: ' + it.url if isinstance(it.url, str) else '...' if it.date_added != '': it.plot += '[CR]' + config.get_localized_string(70469) + ': ' + it.date_added + if it.server: + it.thumbnail = it.contentThumbnail + it.title += ' [{}]'.format(it.serverName) + # If it is not a url, nor does it have the system path, convert the path since it will have been copied from another device. # It would be more optimal if the conversion was done with an import menu, but at the moment it is controlled in run-time. - if it.thumbnail and '://' not in it.thumbnail and not it.thumbnail.startswith(ruta_runtime): - ruta, fichero = filetools.split(it.thumbnail) - if ruta == '' and fichero == it.thumbnail: # in linux the split with a windows path does not separate correctly - ruta, fichero = filetools.split(it.thumbnail.replace('\\','/')) - if 'channels' in ruta and 'thumb' in ruta: - it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'channels', 'thumb', fichero) - elif 'themes' in ruta and 'default' in ruta: - it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'themes', 'default', fichero) + # if it.thumbnail and '://' not in it.thumbnail and not it.thumbnail.startswith(ruta_runtime): + # ruta, fichero = filetools.split(it.thumbnail) + # if ruta == '' and fichero == it.thumbnail: # in linux the split with a windows path does not separate correctly + # ruta, fichero = filetools.split(it.thumbnail.replace('\\','/')) + # if 'channels' in ruta and 'thumb' in ruta: + # it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'channels', 'thumb', fichero) + # elif 'themes' in ruta and 'default' in ruta: + # it.thumbnail = filetools.join(ruta_runtime, 'resources', 'media', 'themes', 'default', fichero) itemlist.append(it) @@ -420,37 +427,30 @@ def editar_enlace_thumbnail(item): # Dialog to choose thumbnail (the channel or predefined icons) opciones = [] ids = [] - try: - from core import channeltools - channel_parameters = channeltools.get_channel_parameters(it.channel) - if channel_parameters['thumbnail'] != '': - nombre = 'Canal %s' % it.channel - if is_kodi17: - it_thumb = xbmcgui.ListItem(nombre) - it_thumb.setArt({ 'thumb': channel_parameters['thumbnail'] }) - opciones.append(it_thumb) - else: - opciones.append(nombre) - ids.append(channel_parameters['thumbnail']) - except: - pass + # try: + # from core import channeltools + # channel_parameters = channeltools.get_channel_parameters(it.channel) + # if channel_parameters['thumbnail'] != '': + # nombre = 'Channel %s' % it.channel + # if is_kodi17: + # it_thumb = xbmcgui.ListItem(nombre) + # it_thumb.setArt({ 'thumb': channel_parameters['thumbnail'] }) + # opciones.append(it_thumb) + # else: + # opciones.append(nombre) + # ids.append(channel_parameters['thumbnail']) + # except: + # pass - resource_path = os.path.join(config.get_runtime_path(), 'resources', 'media', 'themes', 'default') - for f in sorted(os.listdir(resource_path)): - if f.startswith('thumb_') and not f.startswith('thumb_intervenido') and f != 'thumb_back.png': - nombre = f.replace('thumb_', '').replace('_', ' ').replace('.png', '') - if is_kodi17: - it_thumb = xbmcgui.ListItem(nombre) - it_thumb.setArt({ 'thumb': os.path.join(resource_path, f) }) - opciones.append(it_thumb) - else: - opciones.append(nombre) - ids.append(os.path.join(resource_path, f)) + resource_path = 'https://api.github.com/repos/kodiondemand/media/git/trees/b36040432b9be120f04e986277fd34f09dcdb4db' + for f in sorted(requests.get(resource_path).json().get('tree', []), key=lambda p: p.get('path')): + nombre = f['path'].replace('thumb_', '').replace('.png', '') + it_thumb = xbmcgui.ListItem(nombre) + it_thumb.setArt({ 'thumb': support.thumb(nombre)}) + opciones.append(it_thumb) + ids.append(support.thumb(nombre)) - if is_kodi17: - ret = xbmcgui.Dialog().select(config.get_localized_string(70554), opciones, useDetails=True) - else: - ret = platformtools.dialog_select(config.get_localized_string(70554), opciones) + ret = xbmcgui.Dialog().select(config.get_localized_string(70554), opciones, useDetails=True) if ret == -1: return False # order cancel diff --git a/specials/search.py b/specials/search.py index 9b961ac1..d9b6f045 100644 --- a/specials/search.py +++ b/specials/search.py @@ -37,8 +37,8 @@ def mainlist(item): if platformtools.get_window() not in ('WINDOW_SETTINGS_MENU', 'WINDOW_SETTINGS_INTERFACE', 'WINDOW_SKIN_SETTINGS')\ and xbmc.getInfoLabel('System.CurrentWindow') in ('Home', '') and config.get_setting('new_search'): itemlist = [Item(channel='globalsearch', title=config.get_localized_string(70276), action='Search', mode='all', thumbnail=get_thumb("search.png"), folder=False), - Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30122), action='Search', mode='movie', thumbnail=get_thumb("search_movie.png"),folder=False), - Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30123), action='Search', mode='tvshow', thumbnail=get_thumb("search_tvshow.png"), folder=False), + Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30122), action='Search', mode='movie', type='movie', thumbnail=get_thumb("search_movie.png"),folder=False), + Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30123), action='Search', mode='tvshow', type='tvshow',thumbnail=get_thumb("search_tvshow.png"), folder=False), Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(70314), action='Search', page=1, mode='person', thumbnail=get_thumb("search_star.png"), folder=False)] else: itemlist = [Item(channel=item.channel, title=config.get_localized_string(70276), action='new_search', mode='all', thumbnail=get_thumb("search.png")), diff --git a/specials/videolibrary.json b/specials/videolibrary.json index c92a3cbb..97952ade 100644 --- a/specials/videolibrary.json +++ b/specials/videolibrary.json @@ -62,6 +62,7 @@ "type": "list", "label": "@60618", "default": 0, + "visible": false, "enabled": "!eq(-4,@60615)", "lvalues": [ "@60619", @@ -110,7 +111,7 @@ "label": "@60653", "default": true, "enabled": "eq(-1,TVDB)", - "visible": true + "visible": false }, { "id": "info_language", @@ -127,18 +128,6 @@ "pt" ] }, - { - "id": "window_type", - "type": "list", - "label": "@60621", - "default": 0, - "enabled": true, - "visible": true, - "lvalues": [ - "@60622", - "@60623" - ] - }, { "id": "max_links", "type": "list", @@ -162,7 +151,7 @@ "type": "bool", "label": "@60626", "enabled": true, - "visible": true, + "visible": false, "default": false }, { @@ -170,7 +159,7 @@ "type": "bool", "label": "@60627", "enabled": true, - "visible": true, + "visible": false, "default": false }, { @@ -178,7 +167,7 @@ "type": "bool", "label": "@60628", "enabled": "eq(-4,@60623)", - "visible": true, + "visible": false, "default": false }, { @@ -223,7 +212,7 @@ "type": "bool", "label": "@60638", "default": false, - "visible": true, + "visible": false, "enabled": "eq(-3,true)" }, { @@ -231,7 +220,7 @@ "type": "bool", "label": "@60639", "default": true, - "visible": true, + "visible": false, "enabled": "eq(-1,true)" }, { diff --git a/tools/updateDomains.py b/tools/updateDomains.py index 09bf3781..f418265f 100644 --- a/tools/updateDomains.py +++ b/tools/updateDomains.py @@ -16,12 +16,11 @@ def http_Resp(lst_urls): s = httplib2.Http() code, resp = s.request(sito, body=None) if code.previous: - print("r1 http_Resp: %s %s %s %s" % - (code.status, code.reason, code.previous['status'], - code.previous['-x-permanent-redirect-url'])) rslt['code'] = code.previous['status'] - rslt['redirect'] = code.previous['-x-permanent-redirect-url'] + rslt['redirect'] = code.get('content-location', sito) rslt['status'] = code.status + print("r1 http_Resp: %s %s %s %s" % + (code.status, code.reason, rslt['code'], rslt['redirect'])) else: rslt['code'] = code.status except httplib2.ServerNotFoundError as msg: @@ -32,6 +31,7 @@ def http_Resp(lst_urls): # [Errno 111] Connection refused rslt['code'] = 111 except: + print() rslt['code'] = 'Connection error' return rslt @@ -50,6 +50,8 @@ if __name__ == '__main__': print(chann + ' not exists anymore') del data[k][chann] continue + if k == 'findhost': + continue # to get an idea of the timing # useful only if you control all channels # for channels with error 522 about 40 seconds are lost ...