diff --git a/addon.xml b/addon.xml index c104c5fb..3c0db1de 100644 --- a/addon.xml +++ b/addon.xml @@ -1,4 +1,4 @@ - + @@ -18,10 +18,10 @@ resources/media/themes/ss/2.png resources/media/themes/ss/3.png - - completato il supporto ai torrent e aggiunto ilcorsaronero.xyz -- aggiunto supporto agli episodi locali, ovvero poter inserire nella libreria di kodi un misto tra puntate "di kod" e file scaricati altrove -- le viste ora si salvano di nuovo dal menu laterale, ma rimangono salvate per il tipo di contenuto visualizzato e non per il singolo menu -- ripensato il menu rapido, che ora è "più rapido", ridisegnate alcune finestre + - Fix Trakt e aggiuntoi i segni di spunta (già visto) nei canali + - Fix Segna come già visto + - Aggiunta Disattivazione aggiornamento serie tramite multiselect + - Altri fix e migliorie Naviga velocemente sul web e guarda i contenuti presenti [COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR] [COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR] diff --git a/channels.json b/channels.json index 18feb7ed..8219d96d 100644 --- a/channels.json +++ b/channels.json @@ -1,45 +1,44 @@ { - "altadefinizione01": "https://altadefinizione01.photo", - "altadefinizione01_link": "https://altadefinizione01.gallery", - "altadefinizioneclick": "https://altadefinizione.family", - "animeforce": "https://ww1.animeforce.org", - "animeleggendari": "https://animepertutti.org", - "animesaturn": "https://www.animesaturn.com", - "animestream": "https://www.animeworld.it", - "animesubita": "http://www.animesubita.org", - "animetubeita": "http://www.animetubeita.com", - "animeunity": "https://www.animeunity.it", - "animeworld": "https://www.animeworld.tv", - "casacinema": "https://www.casacinema.digital", - "casacinemaInfo": "https://casacinema.life", - "cb01anime": "https://www.cineblog01.network/", - "cinemalibero": "https://cinemalibero.plus", - "cinetecadibologna": "http://cinestore.cinetecadibologna.it", - "dreamsub": "https://dreamsub.stream", - "dsda": "https://www.dsda.press/", - "fastsubita": "https://fastsubita.online", - "filmgratis": "https://www.filmaltadefinizione.tv", - "filmigratis": "https://filmigratis.org", - "filmsenzalimiticc": "https://www.filmsenzalimiti.estate", - "filmstreaming01": "https://filmstreaming01.com", - "guardaserie_stream": "https://guardaserie.store", - "guardaserieclick": "https://www.guardaserie.style", - "hd4me": "https://hd4me.net", - "ilgeniodellostreaming": "https://ilgeniodellostreaming.tw", - "italiaserie": "https://italiaserie.org", - "mondoserietv": "https://mondoserietv.com", - "netfreex": "https://www.netfreex.club", - "piratestreaming": "https://www.piratestreaming.biz", - "polpotv": "https://polpotv.club", - "pufimovies": "https://pufimovies.com", - "raiplay": "https://www.raiplay.it", - "seriehd": "https://seriehd.net", - "serietvonline": "https://serietvonline.host", - "serietvsubita": "http://serietvsubita.xyz", - "serietvu": "https://www.serietvu.link", - "streamtime": "https://t.me/s/StreamTime", - "tantifilm": "https://www.tantifilm.pizza", - "toonitalia": "https://toonitalia.org", - "vedohd": "https://vedohd.uno", + "altadefinizione01": "https://altadefinizione01.photo", + "altadefinizione01_link": "https://altadefinizione01.baby", + "altadefinizioneclick": "https://altadefinizione.family", + "animeforce": "https://ww1.animeforce.org", + "animeleggendari": "https://animepertutti.org", + "animesaturn": "https://www.animesaturn.com", + "animestream": "https://www.animeworld.it", + "animesubita": "http://www.animesubita.org", + "animetubeita": "http://www.animetubeita.com", + "animeunity": "https://www.animeunity.it", + "animeworld": "https://www.animeworld.tv", + "casacinema": "https://www.casacinema.digital", + "casacinemaInfo": "https://casacinema.life", + "cb01anime": "https://www.cineblog01.red/", + "cinemalibero": "https://cinemalibero.plus", + "cinetecadibologna": "http://cinestore.cinetecadibologna.it", + "dreamsub": "https://dreamsub.stream", + "dsda": "https://www.dsda.press/", + "fastsubita": "https://fastsubita.online", + "filmgratis": "https://www.filmaltadefinizione.tv", + "filmigratis": "https://filmigratis.org", + "filmsenzalimiticc": "https://www.filmsenzalimiti.tel", + "filmstreaming01": "https://filmstreaming01.com", + "guardaserie_stream": "https://guardaserie.store", + "guardaserieclick": "https://www.guardaserie.style", + "hd4me": "https://hd4me.net", + "ilgeniodellostreaming": "https://ilgeniodellostreaming.tw", + "italiaserie": "https://italiaserie.org", + "mondoserietv": "https://mondoserietv.com", + "piratestreaming": "https://www.piratestreaming.biz", + "polpotv": "https://polpotv.club", + "pufimovies": "https://pufimovies.com", + "raiplay": "https://www.raiplay.it", + "seriehd": "https://seriehd.net", + "serietvonline": "https://serietvonline.host", + "serietvsubita": "http://serietvsubita.xyz", + "serietvu": "https://www.serietvu.link", + "streamtime": "https://t.me/s/StreamTime", + "tantifilm": "https://www.tantifilm.pizza", + "toonitalia": "https://toonitalia.org", + "vedohd": "https://vedohd.uno", "vvvvid": "https://www.vvvvid.it" } \ No newline at end of file diff --git a/channels/altadefinizioneclick.py b/channels/altadefinizioneclick.py index 573e5987..270dbab5 100644 --- a/channels/altadefinizioneclick.py +++ b/channels/altadefinizioneclick.py @@ -138,5 +138,5 @@ def findvideos(item): support.log('findvideos', item) return support.hdpass_get_servers(item) -# def play(item): -# return support.hdpass_get_url(item) \ No newline at end of file +def play(item): + return support.hdpass_get_url(item) \ No newline at end of file diff --git a/channels/animesubita.json b/channels/animesubita.json index b612eb16..617f6109 100644 --- a/channels/animesubita.json +++ b/channels/animesubita.json @@ -1,7 +1,7 @@ { "id": "animesubita", "name": "AnimeSubIta", - "active": true, + "active": false, "language": ["sub-ita"], "thumbnail": "animesubita.png", "bannermenu": "animesubita.png", diff --git a/channels/animetubeita.json b/channels/animetubeita.json index 1565e785..39384875 100644 --- a/channels/animetubeita.json +++ b/channels/animetubeita.json @@ -1,7 +1,7 @@ { "id": "animetubeita", "name": "AnimeTubeITA", - "active": true, + "active": false, "language": ["sub-ita"], "thumbnail": "animetubeita.png", "bannermenu": "animetubeita.png", diff --git a/channels/animeworld.py b/channels/animeworld.py index c7d09213..c3177aa9 100644 --- a/channels/animeworld.py +++ b/channels/animeworld.py @@ -166,6 +166,8 @@ def findvideos(item): url=url, server='directo', fulltitle=item.fulltitle, + contentSerieName=item.contentSerieName, + contentTitle=item.contentTitle, show=item.show, contentType=item.contentType, folder=False)) diff --git a/channels/casacinemaInfo.py b/channels/casacinemaInfo.py index 0f197609..96eb3f07 100644 --- a/channels/casacinemaInfo.py +++ b/channels/casacinemaInfo.py @@ -126,3 +126,6 @@ def newest(categoria): def findvideos(item): support.log('findvideos ->', item) return support.hdpass_get_servers(item) + +def play(item): + return support.hdpass_get_url(item) \ No newline at end of file diff --git a/channels/dreamsub.py b/channels/dreamsub.py index 7fdc5c35..b05a0a11 100644 --- a/channels/dreamsub.py +++ b/channels/dreamsub.py @@ -137,7 +137,7 @@ def findvideos(item): language = 'ITA' if 'sub' in lang.lower(): language = 'Sub-' + language - quality = url.split('/')[-1] + quality = url.split('/')[-1].split('?')[0] itemlist.append( support.Item(channel=item.channel, diff --git a/channels/eurostreaming.py b/channels/eurostreaming.py index 180a0339..44e29213 100644 --- a/channels/eurostreaming.py +++ b/channels/eurostreaming.py @@ -3,16 +3,8 @@ # Canale per Eurostreaming # by Greko # ------------------------------------------------------------ -""" - Problemi noti da non considerare come errori nel test: - - Alcune sezioni di anime-cartoni non vanno: - - alcune hanno solo la lista degli episodi, ma non hanno link! - Novità(globale): - - serie, anime -""" -import re -from core import scrapertools, httptools, support +from core import httptools, support from core.item import Item def findhost(): @@ -24,7 +16,6 @@ host = support.config.get_channel_url(findhost) headers = [['Referer', host]] - list_servers = ['akstream', 'wstream', 'mixdrop', 'vidtome', 'turbovid', 'speedvideo', 'flashx', 'nowvideo', 'deltabit'] list_quality = ['default'] @@ -33,14 +24,10 @@ def mainlist(item): support.log() - tvshow = ['' - ] - anime = ['/category/anime-cartoni-animati/' - ] - mix = [ - (support.typo('Aggiornamenti Serie-Anime', 'bullet bold'), ['/aggiornamento-episodi/', 'peliculas', 'newest']), - (support.typo('Archivio Serie-Anime', 'bullet bold'), ['/category/serie-tv-archive/', 'peliculas']) - ] + tvshow = [] + anime = ['/category/anime-cartoni-animati/'] + mix = [('Aggiornamenti bullet bold {TV}', ['/aggiornamento-episodi/', 'peliculas', 'newest']), + ('Archivio bullet bold {TV}', ['/category/serie-tv-archive/', 'peliculas'])] search = '' return locals() @@ -48,64 +35,32 @@ def mainlist(item): @support.scrape def peliculas(item): - support.log() - #findhost() action = 'episodios' if item.args == 'newest': patron = r'(?P.*?)[^–â][\s]*<a href="(?P<url>[^"]+)"[^>]*> ?(?P<episode>\d+x\d+-\d+|\d+x\d+) .*?[ ]?\(?(?P<lang>SUB ITA)?\)?</a>' pagination = '' else: patron = r'<div class="post-thumb">.*?\s<img src="(?P<thumb>[^"]+)".*?><a href="(?P<url>[^"]+)"[^>]+>(?P<title>.+?)\s?(?: Serie Tv)?\s?\(?(?P<year>\d{4})?\)?<\/a><\/h2>' - patronNext='a class="next page-numbers" href="?([^>"]+)">Avanti »</a>' + patronNext=r'a class="next page-numbers" href="?([^>"]+)">Avanti »</a>' - # debug = True return locals() @support.scrape def episodios(item): - support.log("episodios: %s" % item) - #findhost() - - action = 'findvideos' - item.contentType = 'tvshow' - # Carica la pagina - data1 = pagina(item.url) - data1 = re.sub('\n|\t', ' ', data1) - data = re.sub(r'>\s+<', '> <', data1) - #patronBlock = r'(?P<block>STAGIONE\s\d+ (.+?)?(?:\()?(?P<lang>ITA|SUB ITA)(?:\))?.*?)</div></div>' + data = support.match(item, headers=headers).data + if 'clicca qui per aprire' in data.lower(): data = support.match(support.match(data, patron=r'"go_to":"([^"]+)"').match.replace('\\',''), headers=headers).data + elif 'clicca qui</span>' in data.lower(): data = support.match(support.match(data, patron=r'<h2 style="text-align: center;"><a href="([^"]+)">').match, headers=headers).data patronBlock = r'</span>(?P<block>[a-zA-Z\s]+\d+(.+?)?(?:\()?(?P<lang>ITA|SUB ITA)(?:\))?.*?)</div></div>' - #patron = r'(?:\s|\Wn)?(?:<strong>|)?(?P<episode>\d+&#\d+;\d+-\d+|\d+&#\d+;\d+)(?:</strong>|)?(?P<title>.+?)(?:–|-.+?-|–.+?–|–|.)?<a (?P<url>.*?)<br />' - patron = r'(?:\s|\Wn)?(?:<strong>|)?(?P<episode>\d+&#\d+;\d+-\d+|\d+&#\d+;\d+)(?:</strong>|)?(?P<title>.+?)(?:–|-.+?-|–.+?–|–|.)?(?:<a (?P<url>.*?))?<br />' + patron = r'(?P<season>\d+)&#\d+;(?P<episode>\d+(?:-\d+)?)\s*(?:</strong>|<em>)?\s*(?P<title>.+?)(?:–|-.+?-|–.+?–|–|em|.)?(?:/em.*?)?(?:<a (?P<url>.*?))?<br />' def itemHook(item): if not item.url: - item.title += ' [B][COLOR red]### NO LINK ###[/COLOR][/B]' + item.url ='' return item - #support.regexDbg(item, patronBlock, headers, data) - #debug = True return locals() -def pagina(url): - support.log(url) - #findhost() - data = httptools.downloadpage(url, headers=headers).data.replace("'", '"') - #support.log("DATA ----###----> ", data) - if 'clicca qui per aprire' in data.lower(): - url = scrapertools.find_single_match(data, '"go_to":"([^"]+)"') - url = url.replace("\\","") - # Carica la pagina - data = httptools.downloadpage(url, headers=headers).data.replace("'", '"') - - elif 'clicca qui</span>' in data.lower(): - url = scrapertools.find_single_match(data, '<h2 style="text-align: center;"><a href="([^"]+)">') - # Carica la pagina - data = httptools.downloadpage(url, headers=headers).data.replace("'", '"') - - return data - -# =========== def ricerca ============= def search(item, texto): support.log() @@ -122,7 +77,6 @@ def search(item, texto): support.log(line) return [] -# =========== def novità in ricerca globale ============= def newest(categoria): support.log() @@ -144,7 +98,7 @@ def newest(categoria): return itemlist -# =========== def findvideos ============= + def findvideos(item): - support.log('findvideos', item) + support.log() return support.server(item, item.url) diff --git a/channels/ilcorsaronero.py b/channels/ilcorsaronero.py index 39941c7d..19f9a82b 100644 --- a/channels/ilcorsaronero.py +++ b/channels/ilcorsaronero.py @@ -93,5 +93,5 @@ def search(item, text): def findvideos(item): if item.contentType == 'tvshow': item.contentType = 'episode' - video_library = True if 'movie' in item.args else False - return support.server(item, support.match(item.url, patron=r'"(magnet[^"]+)').match, video_library=video_library) + Videolibrary = True if 'movie' in item.args else False + return support.server(item, support.match(item.url, patron=r'"(magnet[^"]+)').match, Videolibrary=Videolibrary) diff --git a/channels/metalvideo.py b/channels/metalvideo.py index 823bc40e..9094ac47 100644 --- a/channels/metalvideo.py +++ b/channels/metalvideo.py @@ -50,7 +50,7 @@ def peliculas(item): def findvideos(item): - return support.server(item, video_library=False) + return support.server(item, Videolibrary=False) def search(item, text): diff --git a/channels/netfreex.py b/channels/netfreex.py index 16aea9ae..3c8145d4 100644 --- a/channels/netfreex.py +++ b/channels/netfreex.py @@ -7,7 +7,10 @@ from core import support from core.item import Item from platformcode import logger, config -host = config.get_channel_url() +def findhost(): + return 'https://' + support.match('https://netfreex.uno/', patron='value="site:([^"]+)"').match + +host = config.get_channel_url(findhost) headers = "" IDIOMAS = {'Italiano': 'IT'} diff --git a/channels/raiplay.py b/channels/raiplay.py index c397e563..6f64a539 100644 --- a/channels/raiplay.py +++ b/channels/raiplay.py @@ -292,7 +292,7 @@ def findvideos(item): itemlist.append(support.Item(channel = item.channel, server = 'directo', title = 'Diretto', fulltitle = item.fulltitle, show = item.show, thumbnail = item.thumbnail, fanart = item.json, url = getUrl(url), action = 'play' )) - return support.server(item, itemlist=itemlist, down_load=False) + return support.server(item, itemlist=itemlist, Download=False) def getUrl(pathId): diff --git a/channels/seriehd.py b/channels/seriehd.py index f973f38d..2ed1a8cc 100644 --- a/channels/seriehd.py +++ b/channels/seriehd.py @@ -143,3 +143,6 @@ def findvideos(item): 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): + return support.hdpass_get_url(item) \ No newline at end of file diff --git a/channels/vvvvid.py b/channels/vvvvid.py index 9416fbf1..5a431604 100644 --- a/channels/vvvvid.py +++ b/channels/vvvvid.py @@ -209,7 +209,7 @@ def findvideos(item): url= 'https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/' + url, server= 'directo') ) - return support.server(item, itemlist=itemlist, down_load=False) + return support.server(item, itemlist=itemlist, Download=False) def make_itemlist(itemlist, item, data): search = item.search if item.search else '' diff --git a/core/servertools.py b/core/servertools.py index 0511b9ed..b370a088 100644 --- a/core/servertools.py +++ b/core/servertools.py @@ -19,9 +19,7 @@ else: from future.builtins import range from past.utils import old_div -import datetime import re -import time from core import filetools from core import httptools @@ -32,6 +30,7 @@ from platformcode import platformtools from lib import unshortenit dict_servers_parameters = {} +server_list = {} def find_video_items(item=None, data=None): @@ -154,8 +153,6 @@ def findvideos(data, skip=False): servers_list = list(get_servers_list().keys()) - # Ordenar segun favoriteslist si es necesario - servers_list = sort_servers(servers_list) is_filter_servers = False # Ejecuta el findvideos en cada servidor activo @@ -211,13 +208,43 @@ def guess_server_thumbnail(serverid): def get_server_from_url(url): - encontrado = findvideos(url, True) - if len(encontrado) > 0: - devuelve = encontrado[0][2] - else: - devuelve = "directo" + logger.info() + servers_list = list(get_servers_list().keys()) - return devuelve + # Ejecuta el findvideos en cada servidor activo + for serverid in servers_list: + '''if not is_server_enabled(serverid): + continue''' + if config.get_setting("filter_servers") == True and config.get_setting("black_list", server=serverid): + continue + serverid = get_server_name(serverid) + if not serverid: + continue + server_parameters = get_server_parameters(serverid) + if not server_parameters["active"]: + continue + if "find_videos" in server_parameters: + # Recorre los patrones + for n, pattern in enumerate(server_parameters["find_videos"].get("patterns", [])): + msg = "%s\npattern: %s" % (serverid, pattern["pattern"]) + if not "pattern_compiled" in pattern: + # logger.info('compiled ' + serverid) + pattern["pattern_compiled"] = re.compile(pattern["pattern"]) + dict_servers_parameters[serverid]["find_videos"]["patterns"][n]["pattern_compiled"] = pattern["pattern_compiled"] + # Recorre los resultados + match = re.search(pattern["pattern_compiled"], url) + if match: + url = pattern["url"] + # Crea la url con los datos + for x in range(len(match.groups())): + url = url.replace("\\%s" % (x + 1), match.groups()[x]) + msg += "\nurl encontrada: %s" % url + value = server_parameters["name"], url, serverid, server_parameters.get("thumbnail", "") + if url not in server_parameters["find_videos"].get("ignore_urls", []): + logger.info(msg) + return value + + return None def resolve_video_urls_for_playing(server, url, video_password="", muestra_dialogo=False, background_dialog=False): @@ -654,12 +681,13 @@ def get_servers_list(): y como valor un diccionario con los parametros del servidor. @rtype: dict """ - server_list = {} - for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers")): - if server.endswith(".json") and not server == "version.json": - server_parameters = get_server_parameters(server) - server_list[server.split(".")[0]] = server_parameters - + global server_list + if not server_list: + for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers")): + if server.endswith(".json") and not server == "version.json": + server_parameters = get_server_parameters(server) + server_list[server.split(".")[0]] = server_parameters + server_list = sort_servers(server_list) return server_list @@ -725,9 +753,6 @@ def filter_servers(servers_list): config.get_localized_string(70281)): servers_list = servers_list_filter - if config.get_setting("favorites_servers") == True: - servers_list = sort_servers(servers_list) - return servers_list # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/core/support.py b/core/support.py index 392d532d..245a6cd1 100755 --- a/core/support.py +++ b/core/support.py @@ -37,25 +37,22 @@ def hdpass_get_servers(item): page = httptools.downloadpage(url, CF=False).data mir = scrapertools.find_single_match(page, patron_mir) - with futures.ThreadPoolExecutor() as executor: - thL = [] - for mir_url, srv in scrapertools.find_multiple_matches(mir, patron_option): - mir_url = scrapertools.decodeHtmlentities(mir_url) - log(mir_url) - it = Item(channel=item.channel, - action="play", - fulltitle=item.fulltitle, - quality=quality, - show=item.show, - thumbnail=item.thumbnail, - contentType=item.contentType, - title=srv, - # server=srv, - url= mir_url) - thL.append(executor.submit(hdpass_get_url, it)) - for res in futures.as_completed(thL): - if res.result(): - ret.append(res.result()[0]) + for mir_url, srv in scrapertools.find_multiple_matches(mir, patron_option): + mir_url = scrapertools.decodeHtmlentities(mir_url) + log(mir_url) + it = Item(channel=item.channel, + action="play", + fulltitle=item.fulltitle, + quality=quality, + show=item.show, + thumbnail=item.thumbnail, + contentType=item.contentType, + title=srv, + server=srv, + url= mir_url) + if not servertools.get_server_parameters(srv.lower()): # do not exists or it's empty + it = hdpass_get_url(it)[0] + ret.append(it) return ret # Carica la pagina itemlist = [] @@ -217,8 +214,12 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t if scraped['season']: stagione = scraped['season'] + item.infoLabels['season'] = int(scraped['season']) + item.infoLabels['episode'] = int(scraped['episode']) episode = str(int(scraped['season'])) +'x'+ str(int(scraped['episode'])).zfill(2) elif item.season: + item.infoLabels['season'] = int(item.season) + item.infoLabels['episode'] = int(scrapertools.find_single_match(scraped['episode'], r'(\d+)')) episode = item.season +'x'+ scraped['episode'] elif item.contentType == 'tvshow' and (scraped['episode'] == '' and scraped['season'] == '' and stagione == ''): item.news = 'season_completed' @@ -228,6 +229,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t if 'x' in episode: ep = episode.split('x') episode = str(int(ep[0])).zfill(1) + 'x' + str(int(ep[1])).zfill(2) + item.infoLabels['season'] = int(ep[0]) + item.infoLabels['episode'] = int(ep[1]) second_episode = scrapertools.find_single_match(episode, r'x\d+x(\d+)') if second_episode: episode = re.sub(r'(\d+x\d+)x\d+',r'\1-', episode) + second_episode.zfill(2) @@ -243,14 +246,16 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t if item.infoLabels["title"] == scraped["title"]: infolabels = item.infoLabels else: - infolabels = {} + if function == 'episodios': + infolabels = item.infoLabels + else: + infolabels = {} if scraped['year']: infolabels['year'] = scraped['year'] if scraped["plot"]: infolabels['plot'] = plot if scraped['duration']: - matches = scrapertools.find_multiple_matches(scraped['duration'], - r'([0-9])\s*?(?:[hH]|:|\.|,|\\|\/|\||\s)\s*?([0-9]+)') + matches = scrapertools.find_multiple_matches(scraped['duration'],r'([0-9])\s*?(?:[hH]|:|\.|,|\\|\/|\||\s)\s*?([0-9]+)') for h, m in matches: scraped['duration'] = int(h) * 60 + int(m) if not matches: @@ -331,8 +336,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t infoLabels=infolabels, thumbnail=item.thumbnail if function == 'episodios' or not scraped["thumb"] else scraped["thumb"], args=item.args, - contentSerieName= title if title else item.fulltitle if item.contentType or CT != 'movie' and function != 'episodios' else item.fulltitle if function == 'episodios' else '', - contentTitle= title if item.contentType or CT == 'movie' else '', + contentSerieName= item.contentSerieName if item.contentSerieName else title if 'movie' not in [item.contentType, CT] and function == 'episodios' else item.fulltitle, + contentTitle=item.contentTitle if item.contentTitle else title if 'movie' in [item.contentType, CT] else '', contentLanguage = lang1, contentEpisodeNumber=episode if episode else '', news= item.news if item.news else '', @@ -507,6 +512,10 @@ 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) + return itemlist return wrapper @@ -1103,83 +1112,82 @@ def pagination(itemlist, item, page, perpage, function_level=1): thumbnail=thumb())) return itemlist -def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True, down_load=True, patronTag=None, video_library=True): - +def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True, Download=True, patronTag=None, Videolibrary=True): + log() if not data and not itemlist: data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data if data: itemList = servertools.find_video_items(data=str(data)) itemlist = itemlist + itemList verifiedItemlist = [] - for videoitem in itemlist: - if not videoitem.server: - findS = servertools.findvideos(videoitem.url) - if findS: - findS = findS[0] - elif item.channel == 'community': - findS= ('Diretto', videoitem.url, 'directo') - else: - videoitem.url = unshortenit.unshorten(videoitem.url)[0] - findS = servertools.findvideos(videoitem.url) - if findS: - findS = findS[0] + + def getItem(videoitem): + if not servertools.get_server_parameters(videoitem.server.lower()): # do not exists or it's empty + findS = servertools.get_server_from_url(videoitem.url) + log(findS) + if not findS: + if item.channel == 'community': + findS= ('Diretto', videoitem.url, 'directo') else: - log(videoitem, 'Non supportato') - continue + videoitem.url = unshortenit.unshorten_only(videoitem.url)[0] + findS = servertools.get_server_from_url(videoitem.url) + if not findS: + log(videoitem, 'Non supportato') + return videoitem.server = findS[2] videoitem.title = findS[0] videoitem.url = findS[1] - item.title = typo(item.contentTitle.strip(),'bold') if item.contentType == 'movie' or (config.get_localized_string(30161) in item.title) else item.title + item.title = typo(item.contentTitle.strip(), 'bold') if item.contentType == 'movie' or (config.get_localized_string(30161) in item.title) else item.title - videoitem.plot= typo(videoitem.title, 'bold') + (typo(videoitem.quality, '_ [] bold') if item.quality else '') - videoitem.title = (item.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 "") + quality = videoitem.quality if videoitem.quality else item.quality if item.quality else '' + videoitem.title = (item.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 "") + videoitem.plot= typo(videoitem.title, 'bold') + (typo(quality, '_ [] bold') if quality else '') + videoitem.channel = item.channel videoitem.fulltitle = item.fulltitle videoitem.show = item.show videoitem.thumbnail = item.thumbnail - videoitem.channel = item.channel videoitem.contentType = item.contentType videoitem.infoLabels = item.infoLabels - verifiedItemlist.append(videoitem) + videoitem.quality = quality + return videoitem + with futures.ThreadPoolExecutor() as executor: + thL = [executor.submit(getItem, videoitem) for videoitem in itemlist] + for it in futures.as_completed(thL): + if it.result(): + verifiedItemlist.append(it.result()) + try: + verifiedItemlist.sort(key=lambda it: int(re.sub(r'\D','',it.quality))) + except: + verifiedItemlist.sort(key=lambda it: it.quality, reverse=True) if patronTag: addQualityTag(item, verifiedItemlist, data, patronTag) - return controls(verifiedItemlist, item, AutoPlay, CheckLinks, down_load, video_library) -def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True, video_library=True): - from core import jsontools - from platformcode.config import get_setting - - CL = get_setting('checklinks') or get_setting('checklinks', item.channel) + # Auto Play & Hide Links AP, HS = autoplay.get_channel_AP_HS(item) - if CL and not AP: - if get_setting('checklinks', item.channel): - checklinks = get_setting('checklinks', item.channel) - checklinks_number = get_setting('checklinks_number', item.channel) - else: - checklinks = get_setting('checklinks') - checklinks_number = get_setting('checklinks_number') - itemlist = servertools.check_list_links(itemlist, checklinks_number) + # Check Links + if not AP and (config.get_setting('checklinks') or config.get_setting('checklinks', item.channel)): + if config.get_setting('checklinks', item.channel): + checklinks_number = config.get_setting('checklinks_number', item.channel) + elif config.get_setting('checklinks'): + checklinks_number = config.get_setting('checklinks_number') + verifiedItemlist = servertools.check_list_links(verifiedItemlist, checklinks_number) - if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1]: - autoplay.start(itemlist, item) + if AutoPlay and not 'downloads' in inspect.stack()[3][1] or not 'downloads' in inspect.stack()[3][1] or not inspect.stack()[4][1]: + autoplay.start(verifiedItemlist, item) - if item.contentChannel != 'videolibrary' and video_library: videolibrary(itemlist, item, function_level=3) - if down_load == True: download(itemlist, item, function_level=3) + if Videolibrary and item.contentChannel != 'videolibrary': + videolibrary(verifiedItemlist, item, function_level=3) + if Download: + download(verifiedItemlist, item, function_level=3) + + if not AP or not HS: + # for it in verifiedItemlist: + # log(it) + return verifiedItemlist - VL = False - try: - if 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1] or \ - inspect.stack()[4][3] == 'play_from_library' or \ - inspect.stack()[5][3] == 'play_from_library' or \ - 'videolibrary' in inspect.stack()[3][1] or \ - 'videolibrary' in inspect.stack()[4][1]: - VL = True - except: - pass - if not AP or VL or not HS: - return itemlist def filterLang(item, itemlist): # import channeltools @@ -1197,14 +1205,16 @@ def aplay(item, itemlist, list_servers='', list_quality=''): autoplay.start(itemlist, item) -def log(stringa1="", stringa2="", stringa3="", stringa4="", stringa5=""): +def log(*args): # Function to simplify the log # Automatically returns File Name and Function Name - + string = '' + for arg in args: + string += ' '+str(arg) frame = inspect.stack()[1] filename = frame[0].f_code.co_filename filename = os.path.basename(filename) - logger.info("[" + filename + "] - [" + inspect.stack()[1][3] + "] " + str(stringa1) + ( ' ' + str(stringa2) if stringa2 else '') + ( ' ' + str(stringa3) if stringa3 else '') + ( ' ' + str(stringa4) if stringa4 else '') + ( ' ' + str(stringa5) if stringa5 else '') ) + logger.info("[" + filename + "] - [" + inspect.stack()[1][3] + "] " + string) def channel_config(item, itemlist): @@ -1302,9 +1312,12 @@ def addQualityTag(item, itemlist, data, patron): def get_jwplayer_mediaurl(data, srvName): video_urls = [] block = scrapertools.find_single_match(data, r'sources: \[([^\]]+)\]') - sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?') - if not sources: + if 'file:' in block: + sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?') + elif 'src:' in block: sources = scrapertools.find_multiple_matches(data, r'src:\s*"([^"]+)",\s*type:\s*"[^"]+",[^,]+,\s*label:\s*"([^"]+)"') + else: + sources =[(block.replace('"',''), '')] for url, quality in sources: quality = 'auto' if not quality else quality if url.split('.')[-1] != 'mpd': diff --git a/core/tmdb.py b/core/tmdb.py index 18b7464d..2fd82ba5 100644 --- a/core/tmdb.py +++ b/core/tmdb.py @@ -984,7 +984,7 @@ class Tmdb(object): url += '&year=%s' % self.busqueda_year buscando = self.busqueda_texto.capitalize() - logger.info("[Tmdb.py] Buscando %s en pagina %s:\n%s" % (buscando, page, url)) + logger.info("[Tmdb.py] Searching %s on page %s:\n%s" % (buscando, page, url)) resultado = self.get_json(url) if not isinstance(resultado, dict): resultado = ast.literal_eval(resultado.decode('utf-8')) diff --git a/core/trakt_tools.py b/core/trakt_tools.py index 743e5fbb..d78e1852 100644 --- a/core/trakt_tools.py +++ b/core/trakt_tools.py @@ -8,6 +8,9 @@ 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 client_id = "502bd1660b833c1ae69828163c0848e84e9850061e5529f30930e7356cae73b1" client_secret = "1d30d5b24acf223a5e1ab6c61d08b69992d98ed5b0c7e26b052b5e6a592035a4" @@ -196,58 +199,37 @@ def get_trakt_watched(id_type, mediatype, update=False): def trakt_check(itemlist): - from core.support import typo - id_result = '' - # check = u'\u221a' - check = typo(u'\u221a','[] color kod bold')+' ' - synced = False - try: - for item in itemlist: - info = item.infoLabels + def sync(item, id_result): + info = item.infoLabels + try: + if info['mediatype'] == 'movie' and info['tmdb_id'] in id_result[info['mediatype']]: + item.infoLabels['playcount'] = 1 + elif info['mediatype'] == 'episode' and info['tmdb_id'] in id_result[info['mediatype']]: + id = info['tmdb_id'] + if info['season'] and info['episode'] and \ + str(info['season']) in id_result[info['mediatype']][id] and \ + str(info['episode']) in id_result[info['mediatype']][id][str(info['season'])]: + item.infoLabels['playcount'] = 1 + except: + pass - if info != '' and info['mediatype'] in ['movie', 'episode'] and item.channel != 'videolibrary': + if itemlist and itemlist[0].channel != 'videolibrary' \ + and 'mediatype' in itemlist[0].infoLabels \ + and itemlist[0].infoLabels['mediatype'] in ['movie', 'episode']: - if not synced: - get_sync_from_file() - synced = True + id_result = {} + id_result['movie'] = get_trakt_watched('tmdb', 'movies', True) + id_result['episode'] = get_trakt_watched('tmdb', 'shows', True) - mediatype = 'movies' - id_type = 'tmdb' - - if info['mediatype'] == 'episode': - mediatype = 'shows' - - if id_result == '': - id_result = get_trakt_watched(id_type, mediatype) - if info['mediatype'] == 'movie': - if info[id_type + '_id'] in id_result: - item.title = check + item.title - - elif info['mediatype'] == 'episode': - if info[id_type + '_id'] in id_result: - id = info[id_type + '_id'] - if info['season'] != '' and info['episode'] != '': - season = str(info['season']) - - if season in id_result[id]: - episode = str(info['episode']) - - if episode in id_result[id][season]: - season_watched = id_result[id][season] - - if episode in season_watched: - item.title = check + item.title - else: - break - except: - pass + with futures.ThreadPoolExecutor() as executor: + [executor.submit(sync, it, id_result) for it in itemlist] return itemlist def get_sync_from_file(): logger.info() - sync_path = os.path.join(config.get_data_path(), 'settings_channels', 'trakt') + sync_path = os.path.join(config.get_data_path(), 'settings_channels', 'trakt_data.json') trakt_node = {} if os.path.exists(sync_path): trakt_node = jsontools.get_node_from_file('trakt', "TRAKT") @@ -260,7 +242,7 @@ def get_sync_from_file(): def update_trakt_data(mediatype, trakt_data): logger.info() - sync_path = os.path.join(config.get_data_path(), 'settings_channels', 'trakt') + sync_path = os.path.join(config.get_data_path(), 'settings_channels', 'trakt_data.json') if os.path.exists(sync_path): trakt_node = jsontools.get_node_from_file('trakt', "TRAKT") trakt_node[mediatype] = trakt_data @@ -289,6 +271,7 @@ def wait_for_update_trakt(): t.isAlive() def update_all(): + # from core.support import dbg;dbg() from time import sleep logger.info() sleep(20) diff --git a/core/tvdb.py b/core/tvdb.py index f5674d69..fd56e864 100644 --- a/core/tvdb.py +++ b/core/tvdb.py @@ -2,14 +2,12 @@ # ------------------------------------------------------------ # tvdb # ------------------------------------------------------------ -# Scraper para el site thetvdb.com usando API v2.1 -# Utilizado para obtener datos de series para la videoteca -# del addon y también Kodi. +# Scraper for thetvdb.com using API v2.1 +# Used to obtain series data for the video library # ------------------------------------------------------------ from future import standard_library standard_library.install_aliases() -#from builtins import str from future.builtins import object import urllib.request, urllib.error, urllib.parse @@ -35,41 +33,41 @@ DEFAULT_HEADERS = { 'Authorization': 'Bearer ' + TOKEN, } -# Traducciones - Inicio -DICT_STATUS = {'Continuing': 'En emisión', 'Ended': 'Finalizada'} -DICT_GENRE = { - 'Action': 'Acción', - 'Adventure': 'Aventura', - 'Animation': 'Animación', - 'Children': 'Niños', - 'Comedy': 'Comedia', - 'Crime': 'Crimen', - 'Documentary': 'Documental', - # 'Drama': 'Drama', - 'Family': 'Familiar', - 'Fantasy': 'Fantasía', - 'Food': 'Comida', - 'Game Show': 'Concurso', - 'Home and Garden': 'Hogar y Jardín', - # 'Horror': 'Horror', 'Mini-Series': 'Mini-Series', - 'Mystery': 'Misterio', - 'News': 'Noticias', - # 'Reality': 'Telerrealidad', - 'Romance': 'Romántico', - 'Science-Fiction': 'Ciencia-Ficción', - 'Soap': 'Telenovela', - # 'Special Interest': 'Special Interest', - 'Sport': 'Deporte', - # 'Suspense': 'Suspense', - 'Talk Show': 'Programa de Entrevistas', - # 'Thriller': 'Thriller', - 'Travel': 'Viaje', - # 'Western': 'Western' -} -DICT_MPAA = {'TV-Y': 'Público pre-infantil: niños menores de 6 años', 'TV-Y7': 'Público infantil: desde 7 años', - 'TV-G': 'Público general: sin supervisión familiar', 'TV-PG': 'Guía paterna: Supervisión paternal', - 'TV-14': 'Mayores de 14 años', 'TV-MA': 'Mayores de 17 años'} -# Traducciones - Fin +# # Traducciones - Inicio +# DICT_STATUS = {'Continuing': 'En emisión', 'Ended': 'Finalizada'} +# DICT_GENRE = { +# 'Action': 'Acción', +# 'Adventure': 'Aventura', +# 'Animation': 'Animación', +# 'Children': 'Niños', +# 'Comedy': 'Comedia', +# 'Crime': 'Crimen', +# 'Documentary': 'Documental', +# # 'Drama': 'Drama', +# 'Family': 'Familiar', +# 'Fantasy': 'Fantasía', +# 'Food': 'Comida', +# 'Game Show': 'Concurso', +# 'Home and Garden': 'Hogar y Jardín', +# # 'Horror': 'Horror', 'Mini-Series': 'Mini-Series', +# 'Mystery': 'Misterio', +# 'News': 'Noticias', +# # 'Reality': 'Telerrealidad', +# 'Romance': 'Romántico', +# 'Science-Fiction': 'Ciencia-Ficción', +# 'Soap': 'Telenovela', +# # 'Special Interest': 'Special Interest', +# 'Sport': 'Deporte', +# # 'Suspense': 'Suspense', +# 'Talk Show': 'Programa de Entrevistas', +# # 'Thriller': 'Thriller', +# 'Travel': 'Viaje', +# # 'Western': 'Western' +# } +# DICT_MPAA = {'TV-Y': 'Público pre-infantil: niños menores de 6 años', 'TV-Y7': 'Público infantil: desde 7 años', +# 'TV-G': 'Público general: sin supervisión familiar', 'TV-PG': 'Guía paterna: Supervisión paternal', +# 'TV-14': 'Mayores de 14 años', 'TV-MA': 'Mayores de 17 años'} +# # Traducciones - Fin otvdb_global = None @@ -86,7 +84,7 @@ def find_and_set_infoLabels(item): tvdb_result = None title = item.contentSerieName - # Si el titulo incluye el (año) se lo quitamos + # If the title includes the (year) we will remove it year = scrapertools.find_single_match(title, "^.+?\s*(\(\d{4}\))$") if year: title = title.replace(year, "").strip() @@ -104,24 +102,23 @@ def find_and_set_infoLabels(item): if not item.contentSeason: p_dialog.update(50, config.get_localized_string(60296), config.get_localized_string(60295)) results, info_load = otvdb_global.get_list_results() - logger.debug("results es %s" % results) + logger.debug("results: %s" % results) if not item.contentSeason: p_dialog.update(100, config.get_localized_string(60296), config.get_localized_string(60297) % len(results)) p_dialog.close() if len(results) > 1: - tvdb_result = platformtools.show_video_info(results, item=item, scraper=Tvdb, - caption=config.get_localized_string(60298) % title) + tvdb_result = platformtools.show_video_info(results, item=item, scraper=Tvdb, caption=config.get_localized_string(60298) % title) elif len(results) > 0: tvdb_result = results[0] # todo revisar if isinstance(item.infoLabels, InfoLabels): - logger.debug("es instancia de infoLabels") + logger.debug("is an instance of infoLabels") infoLabels = item.infoLabels else: - logger.debug("NO ES instancia de infoLabels") + logger.debug("NOT an instance of infoLabels") infoLabels = InfoLabels() if tvdb_result: @@ -146,12 +143,9 @@ def find_and_set_infoLabels(item): def set_infoLabels_item(item): """ - Obtiene y fija (item.infoLabels) los datos extras de una serie, capitulo o pelicula. - @param item: Objeto que representa un pelicula, serie o capitulo. El atributo infoLabels sera modificado - incluyendo los datos extras localizados. + Gets and sets (item.infoLabels) the extra data of a series, chapter or movie. + @param item: Object that represents a movie, series or chapter. The infoLabels attribute will be modified including the extra localized data. @type item: Item - - """ global otvdb_global @@ -166,7 +160,7 @@ def set_infoLabels_item(item): try: int_season = int(item.infoLabels['season']) except ValueError: - logger.debug("El numero de temporada no es valido") + logger.debug("The season number is not valid") item.contentType = item.infoLabels['mediatype'] return -1 * len(item.infoLabels) @@ -184,12 +178,12 @@ def set_infoLabels_item(item): try: int_episode = int(item.infoLabels['episode']) except ValueError: - logger.debug("El número de episodio (%s) no es valido" % repr(item.infoLabels['episode'])) + logger.debug("The episode number (%s) is not valid" % repr(item.infoLabels['episode'])) item.contentType = item.infoLabels['mediatype'] return -1 * len(item.infoLabels) - # Tenemos numero de temporada y numero de episodio validos... - # ... buscar datos episodio + # We have a valid season number and episode number ... + # ... search episode data item.infoLabels['mediatype'] = 'episode' lang = DEFAULT_LANG @@ -211,7 +205,7 @@ def set_infoLabels_item(item): t.start() l_hilo.append(t) - # esperar q todos los hilos terminen + # wait for all the threads to end for x in l_hilo: x.join() @@ -228,7 +222,7 @@ def set_infoLabels_item(item): data_episode = otvdb_global.get_info_episode(otvdb_global.get_id(), int_season, int_episode, lang, _id) - # todo repasar valores que hay que insertar en infoLabels + # all go over values ​​to insert into infoLabels if data_episode: item.infoLabels['title'] = data_episode['episodeName'] # fix en casos que el campo desde la api era null--> None @@ -252,15 +246,15 @@ def set_infoLabels_item(item): l_castandrole.extend([(p, '') for p in guest_stars]) item.infoLabels['castandrole'] = l_castandrole - # datos para nfo + # data for nfo item.season_id = data_episode["airedSeasonID"] item.episode_id = data_episode["id"] return len(item.infoLabels) else: - # Tenemos numero de temporada valido pero no numero de episodio... - # ... buscar datos temporada + # We have a valid season number but no episode number ... + # ... search season data item.infoLabels['mediatype'] = 'season' data_season = otvdb_global.get_images(otvdb_global.get_id(), "season", int_season) @@ -268,9 +262,9 @@ def set_infoLabels_item(item): item.thumbnail = HOST_IMAGE + data_season['image_season_%s' % int_season][0]['fileName'] return len(item.infoLabels) - # Buscar... + # Search... else: - # Busquedas por ID... + # Search by ID ... if (not otvdb_global or otvdb_global.get_id() != item.infoLabels['tvdb_id']) and item.infoLabels['tvdb_id']: otvdb_global = Tvdb(tvdb_id=item.infoLabels['tvdb_id']) @@ -280,29 +274,28 @@ def set_infoLabels_item(item): elif not otvdb_global and item.infoLabels['zap2it_id']: otvdb_global = Tvdb(zap2it_id=item.infoLabels['zap2it_id']) - # No se ha podido buscar por ID... se hace por título + # Unable to search by ID ... done by title if otvdb_global is None: otvdb_global = Tvdb(search=item.infoLabels['tvshowtitle']) if otvdb_global and otvdb_global.get_id(): __leer_datos(otvdb_global) - # La busqueda ha encontrado un resultado valido + # The search has found a valid result return len(item.infoLabels) def get_nfo(item): """ - Devuelve la información necesaria para que se scrapee el resultado en la videoteca de kodi, + Returns the information necessary for the result to be scraped into the kodi video library, - @param item: elemento que contiene los datos necesarios para generar la info + @param item: element that contains the data necessary to generate the info @type item: Item @rtype: str @return: """ if "season" in item.infoLabels and "episode" in item.infoLabels: - info_nfo = "http://thetvdb.com/?tab=episode&seriesid=%s&seasonid=%s&id=%s\n" \ - % (item.infoLabels['tvdb_id'], item.season_id, item.episode_id) + info_nfo = "http://thetvdb.com/?tab=episode&seriesid=%s&seasonid=%s&id=%s\n" % (item.infoLabels['tvdb_id'], item.season_id, item.episode_id) else: info_nfo = ', '.join(item.infoLabels['url_scraper']) + "\n" @@ -311,7 +304,7 @@ def get_nfo(item): def completar_codigos(item): """ - Si es necesario comprueba si existe el identificador de tmdb y sino existe trata de buscarlo + If necessary, check if the tmdb identifier exists and if it does not exist try to find it @param item: tipo item @type item: Item """ @@ -347,27 +340,25 @@ class Tvdb(object): self.episodes = {} if kwargs.get('tvdb_id', ''): - # Busqueda por identificador tvdb + # Search by tvdb identifier self.__get_by_id(kwargs.get('tvdb_id', '')) if not self.list_results and config.get_setting("tvdb_retry_eng", "videolibrary"): from platformcode import platformtools - platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, - config.get_localized_string(60302), sound=False) + platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, config.get_localized_string(60302), sound=False) self.__get_by_id(kwargs.get('tvdb_id', ''), "en") self.lang = "en" elif self.search_name: - # Busqueda por texto + # BUsqueda by text self.__search(kwargs.get('search', ''), kwargs.get('imdb_id', ''), kwargs.get('zap2it_id', '')) if not self.list_results and config.get_setting("tvdb_retry_eng", "videolibrary"): from platformcode import platformtools - platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, - config.get_localized_string(60302)) + platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, config.get_localized_string(60302)) self.__search(kwargs.get('search', ''), kwargs.get('imdb_id', ''), kwargs.get('zap2it_id', ''), "en") self.lang = "en" if not self.result: - # No hay resultados de la busqueda + # No search results if kwargs.get('tvdb_id', ''): buscando = kwargs.get('tvdb_id', '') else: @@ -381,12 +372,12 @@ class Tvdb(object): if TOKEN == "": cls.__login() else: - # si la fecha no se corresponde con la actual llamamos a refresh_token, ya que el token expira en 24 horas + # if the date does not correspond to the current one we call refresh_token, since the token expires in 24 hours from time import gmtime, strftime current_date = strftime("%Y-%m-%d", gmtime()) if config.get_setting("tvdb_token_date", "") != current_date: - # si se ha renovado el token grabamos la nueva fecha + # if the token has been renewed we save the new date if cls.__refresh_token(): config.set_setting("tvdb_token_date", current_date) @@ -408,7 +399,7 @@ class Tvdb(object): except Exception as ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: dict_html = jsontools.load(html) @@ -435,8 +426,8 @@ class Tvdb(object): response.close() except urllib.error.HTTPError as err: - logger.error("err.code es %s" % err.code) - # si hay error 401 es que el token se ha pasado de tiempo y tenemos que volver a llamar a login + logger.error("err.code %s" % err.code) + # if there is error 401 it is that the token has passed the time and we have to call login again if err.code == 401: cls.__login() else: @@ -444,7 +435,7 @@ class Tvdb(object): except Exception as ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: dict_html = jsontools.load(html) @@ -459,16 +450,16 @@ class Tvdb(object): def get_info_episode(self, _id, season=1, episode=1, lang=DEFAULT_LANG, id_episode=None): """ - Devuelve los datos de un episodio. - @param _id: identificador de la serie + Returns the data of an episode. + @param _id: series identifier @type _id: str - @param season: numero de temporada [por defecto = 1] + @param season: season number [default = 1] @type season: int - @param episode: numero de episodio [por defecto = 1] + @param episode: episode number [default = 1] @type episode: int - @param lang: codigo de idioma para buscar + @param lang: language code to search @type lang: str - @param id_episode: codigo del episodio. + @param id_episode: episode code. @type id_episode: int @rtype: dict @return: @@ -541,7 +532,7 @@ class Tvdb(object): except Exception as ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: dict_html = jsontools.load(html) @@ -552,10 +543,10 @@ class Tvdb(object): def get_list_episodes(self, _id, page=1): """ - Devuelve el listado de episodios de una serie. - @param _id: identificador de la serie + Returns the list of episodes of a series. + @param _id: series identifier @type _id: str - @param page: numero de pagina a buscar [por defecto = 1] + @param page: page number to search [default = 1] @type page: int @rtype: dict @return: @@ -604,7 +595,7 @@ class Tvdb(object): except Exception as ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: self.list_episodes[page] = jsontools.load(html) @@ -615,11 +606,11 @@ class Tvdb(object): def get_episode_by_id(self, _id, lang=DEFAULT_LANG, semaforo=None): """ - Obtiene los datos de un episodio - @param _id: identificador del episodio + Get the data of an episode + @param _id: episode identifier @type _id: str - @param lang: código de idioma - @param semaforo: semaforo para multihilos + @param lang: language code + @param semaforo: semaphore for multihilos @type semaforo: threading.Semaphore @type lang: str @rtype: dict @@ -691,7 +682,7 @@ class Tvdb(object): except Exception as ex: # if isinstance(ex, urllib).HTTPError: - logger.debug("code es %s " % ex.code) + logger.debug("code %s " % ex.code) message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) logger.error("error en: %s" % message) @@ -708,14 +699,14 @@ class Tvdb(object): def __search(self, name, imdb_id, zap2it_id, lang=DEFAULT_LANG): """ - Busca una serie a través de una serie de parámetros. - @param name: nombre a buscar + Search for a series through a series of parameters. + @param name: name to search @type name: str - @param imdb_id: codigo identificativo de imdb + @param imdb_id: imdb identification code @type imdb_id: str - @param zap2it_id: codigo identificativo de zap2it + @param zap2it_id: zap2it identification code @type zap2it_id: str - @param lang: código de idioma + @param lang: language code @type lang: str data:{ @@ -756,10 +747,10 @@ class Tvdb(object): except Exception as ex: # if isinstance(ex, urllib.parse).HTTPError: - logger.debug("code es %s " % ex.code) + logger.debug("code %s " % ex.code) message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: dict_html = jsontools.load(html) @@ -777,16 +768,16 @@ class Tvdb(object): else: index = 0 - logger.debug("resultado %s" % resultado) + logger.debug("result %s" % resultado) self.list_results = resultado self.result = resultado[index] def __get_by_id(self, _id, lang=DEFAULT_LANG, from_get_list=False): """ - Obtiene los datos de una serie por identificador. - @param _id: código de la serie + Gets the data for a string by identifier. + @param _id: series code @type _id: str - @param lang: código de idioma + @param lang: language code @type lang: str @rtype: dict @return: @@ -845,10 +836,10 @@ class Tvdb(object): except Exception as ex: # if isinstance(ex, urllib).HTTPError: - logger.debug("code es %s " % ex.code) + logger.debug("code %s " % ex.code) message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) else: dict_html = jsontools.load(html) @@ -860,7 +851,7 @@ class Tvdb(object): if not resultado1 and from_get_list: return self.__get_by_id(_id, "en") - logger.debug("resultado %s" % dict_html) + logger.debug("Result %s" % dict_html) resultado2 = {"image_poster": [{'keyType': 'poster', 'fileName': 'posters/%s-1.jpg' % _id}]} resultado3 = {"image_fanart": [{'keyType': 'fanart', 'fileName': 'fanart/original/%s-1.jpg' % _id}]} @@ -868,7 +859,7 @@ class Tvdb(object): resultado.update(resultado2) resultado.update(resultado3) - logger.debug("resultado total %s" % resultado) + logger.debug("total result %s" % resultado) self.list_results = [resultado] self.result = resultado @@ -876,15 +867,15 @@ class Tvdb(object): def get_images(self, _id, image="poster", season=1, lang="en"): """ - Obtiene un tipo de imagen para una serie para un idioma. - @param _id: identificador de la serie + Gets an image type for a string for a language. + @param _id: series identifier @type _id: str - @param image: codigo de busqueda, ["poster" (por defecto), "fanart", "season"] + @param image: search code, ["poster" (default), "fanart", "season"] @type image: str - @type season: numero de temporada - @param lang: código de idioma para el que se busca + @type season: season number + @param lang: language code for which you are searching @type lang: str - @return: diccionario con el tipo de imagenes elegidas. + @return: dictionary with the type of images chosen. @rtype: dict """ @@ -918,7 +909,7 @@ class Tvdb(object): except Exception as ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error: %s" % message) return {} @@ -932,12 +923,12 @@ class Tvdb(object): def get_tvshow_cast(self, _id, lang=DEFAULT_LANG): """ - obtiene el casting de una serie - @param _id: codigo de la serie + gets casting for a series + @param _id: series code @type _id: str - @param lang: codigo idioma para buscar + @param lang: language code to search @type lang: str - @return: diccionario con los actores + @return: dictionary with actors @rtype: dict """ logger.info() @@ -958,23 +949,22 @@ class Tvdb(object): def get_id(self): """ - @return: Devuelve el identificador Tvdb de la serie cargada o una cadena vacia en caso de que no - hubiese nada cargado. Se puede utilizar este metodo para saber si una busqueda ha dado resultado o no. + @return: Returns the Tvdb identifier of the loaded string or an empty string in case nothing was loaded. + You can use this method to find out if a search has been successful or not. @rtype: str """ return str(self.result.get('id', "")) def get_list_results(self): """ - Devuelve los resultados encontramos para una serie. + Returns the results we found for a series. @rtype: list - @return: lista de resultados + @return: list of results """ logger.info() list_results = [] - # TODO revisar condicion - # si tenemos un resultado y tiene seriesName, ya tenemos la info de la serie, no hace falta volver a buscar + # if we have a result and it has seriesName, we already have the info of the series, it is not necessary to search again if len(self.list_results) == 1 and "seriesName" in self.result: list_results.append(self.result) info_load = True @@ -1005,16 +995,15 @@ class Tvdb(object): def get_infoLabels(self, infoLabels=None, origen=None): """ - @param infoLabels: Informacion extra de la pelicula, serie, temporada o capitulo. + @param infoLabels: Extra information about the movie, series, season or chapter. @type infoLabels: dict @param origen: Diccionario origen de donde se obtiene los infoLabels, por omision self.result @type origen: dict - @return: Devuelve la informacion extra obtenida del objeto actual. Si se paso el parametro infoLables, el valor - devuelto sera el leido como parametro debidamente actualizado. + @return: Returns the extra information obtained from the current object. If the infoLables parameter was passed, + the value returned will be read as a parameter duly updated. @rtype: dict """ - # TODO revisar if infoLabels: # logger.debug("es instancia de infoLabels") ret_infoLabels = InfoLabels(infoLabels) @@ -1024,7 +1013,7 @@ class Tvdb(object): # fix ret_infoLabels['mediatype'] = 'tvshow' - # Iniciar listados + # Start Listings l_castandrole = ret_infoLabels.get('castandrole', []) # logger.debug("self.result %s" % self.result) @@ -1067,9 +1056,9 @@ class Tvdb(object): elif k == 'status': # se traduce los estados de una serie - ret_infoLabels['status'] = DICT_STATUS.get(v, v) + ret_infoLabels['status'] = v - # no soy partidario de poner la cadena como studio pero es como lo hace el scraper de manera genérica + # I am not in favor of putting the chain as a studio but it is how the scraper does it in a generic way elif k == 'network': ret_infoLabels['studio'] = v @@ -1094,8 +1083,8 @@ class Tvdb(object): # ret_infoLabels['code'] = v elif k in "rating": - # traducimos la clasificación por edades (content rating system) - ret_infoLabels['mpaa'] = DICT_MPAA.get(v, v) + # we translate the age rating (content rating system) + ret_infoLabels['mpaa'] = v elif k in "genre": genre_list = "" @@ -1104,7 +1093,7 @@ class Tvdb(object): genre_list += ", " # traducimos los generos - genre_list += DICT_GENRE.get(i, i) + genre_list += i ret_infoLabels['genre'] = genre_list @@ -1121,10 +1110,10 @@ class Tvdb(object): l_castandrole.extend([(p['name'], p['role']) for p in v if p['name'] not in list(dic_aux.keys())]) else: - logger.debug("Atributos no añadidos: %s=%s" % (k, v)) + logger.debug("Attributes not added: %s=%s" % (k, v)) pass - # Ordenar las listas y convertirlas en str si es necesario + # Sort the lists and convert them to str if necessary if l_castandrole: ret_infoLabels['castandrole'] = l_castandrole diff --git a/lib/megaserver/cursor.py b/lib/megaserver/cursor.py index 3a3f2693..ec387b9c 100644 --- a/lib/megaserver/cursor.py +++ b/lib/megaserver/cursor.py @@ -66,15 +66,8 @@ class Cursor(object): def prepare_decoder(self,offset): initial_value = self.initial_value + int(offset/16) - try: - from Cryptodome.Cipher import AES - from Cryptodome.Util import Counter - self.decryptor = AES.new(self._file._client.a32_to_str(self.k), AES.MODE_CTR, counter = Counter.new(128, initial_value = initial_value)) - except: - from Crypto.Cipher import AES - from Crypto.Util import Counter - self.decryptor = AES.new(self._file._client.a32_to_str(self.k), AES.MODE_CTR, counter = Counter.new(128, initial_value = initial_value)) - + from lib import pyaes + self.decryptor = pyaes.AESModeOfOperationCTR(self._file._client.a32_to_str(self.k), counter=pyaes.Counter(initial_value=initial_value)) rest = offset - int(offset/16)*16 if rest: self.decode(str(0)*rest) diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index d9f85ae9..cc77c3bd 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -581,7 +581,7 @@ def set_infolabels(listitem, item, player=False): listitem.setInfo("video", infoLabels_kodi) except: listitem.setInfo("video", item.infoLabels) - logger.error(item.infoLabels) + # logger.error(item.infoLabels) # if item.infoLabels: # if 'mediatype' not in item.infoLabels: diff --git a/platformcode/updater.py b/platformcode/updater.py index b12cad12..cfb00989 100644 --- a/platformcode/updater.py +++ b/platformcode/updater.py @@ -101,6 +101,7 @@ def check(background=False): localCommitFile = open(os.path.join(xbmc.translatePath("special://home/addons/"), 'plugin.video.kod', trackingFile), 'w') # il file di tracking viene eliminato, lo ricreo changelog += commitJson['commit']['message'] + "\n" poFilesChanged = True + serviceChanged = True break for file in commitJson['files']: @@ -172,13 +173,6 @@ def check(background=False): localCommitFile = open( os.path.join(xbmc.translatePath("special://home/addons/"), 'plugin.video.kod', trackingFile), 'w') # il file di tracking viene eliminato, lo ricreo - if addon.getSetting("addon_update_message"): - if background: - platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(80040) % commits[0]['sha'][:7], time=3000, sound=False) - with open(xbmc.translatePath(changelogFile), 'a+') as fileC: - fileC.write(changelog) - elif changelog: - platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80041) + changelog) localCommitFile.seek(0) localCommitFile.truncate() @@ -188,6 +182,14 @@ def check(background=False): if poFilesChanged: refreshLang() updated = True + + if addon.getSetting("addon_update_message"): + if background: + platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(80040) % commits[0]['sha'][:7], time=3000, sound=False) + with open(xbmc.translatePath(changelogFile), 'a+') as fileC: + fileC.write(changelog) + elif changelog: + platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80041) + changelog) else: logger.info('Nessun nuovo aggiornamento') diff --git a/platformcode/xbmc_videolibrary.py b/platformcode/xbmc_videolibrary.py index e7c8551f..d64a8e01 100644 --- a/platformcode/xbmc_videolibrary.py +++ b/platformcode/xbmc_videolibrary.py @@ -80,7 +80,7 @@ def mark_auto_as_watched(item): videolibrary.mark_content_as_watched2(item) break - time.sleep(30) + time.sleep(5) # Sincronizacion silenciosa con Trakt if sync_with_trakt and config.get_setting("trakt_sync"): @@ -420,7 +420,7 @@ def mark_content_as_watched_on_kod(path): elif not PY3 and isinstance(title_plain, (str, unicode)): title_plain = title_plain.decode("utf-8").encode("utf-8") #Hacemos esto porque si no genera esto: u'title_plain' - elif PY3 and isinstance(var, bytes): + elif PY3 and isinstance(title_plain, bytes): title_plain = title_plain.decode('utf-8') item.library_playcounts.update({title_plain: playCount_final}) #actualizamos el playCount del .nfo @@ -829,6 +829,11 @@ def update_db(old_path, new_path, old_movies_folder, new_movies_folder, old_tvsh sql = 'UPDATE path SET strPath="%s" WHERE idPath=%s' % (strPath, idPath) logger.info('sql: ' + sql) nun_records, records = execute_sql_kodi(sql) + else: + progress.update(100) + xbmc.sleep(1000) + progress.close() + return p = 80 progress.update(p, config.get_localized_string(20000), config.get_localized_string(80013)) diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index e8eeecb9..efb72699 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -2504,6 +2504,10 @@ msgctxt "#60598" msgid "Video library configuration" msgstr "" +msgctxt "#60599" +msgid "Video library update configuration" +msgstr "" + msgctxt "#60600" msgid "TV shows" msgstr "" @@ -5181,7 +5185,7 @@ msgid "Remove" msgstr "" msgctxt "#70600" -msgid "Add Season" +msgid "Add season" msgstr "" msgctxt "#70601" @@ -6011,6 +6015,10 @@ msgctxt "#70806" msgid "Changing this parameter permanently overwrites the Elementum settings.\nDo you want to continue?" msgstr "" +msgctxt "#70807" +msgid "Elementum does not support network folder downloads, do you want to change the download location?" +msgstr "Elementum non supporta i download su cartella di rete, vuoi cambiare il percorso di download?" + # DNS start [ settings and declaration ] msgctxt "#707401" msgid "Enable DNS check alert" diff --git a/resources/language/Italian/strings.po b/resources/language/Italian/strings.po index 4d226744..f6010cf2 100644 --- a/resources/language/Italian/strings.po +++ b/resources/language/Italian/strings.po @@ -2503,6 +2503,10 @@ msgctxt "#60598" msgid "Video library configuration" msgstr "Configurazione videoteca" +msgctxt "#60599" +msgid "Video library update configuration" +msgstr "Configurazione aggiornamento videoteca" + msgctxt "#60600" msgid "TV shows" msgstr "Serie TV" @@ -3389,7 +3393,7 @@ msgstr "Server" msgctxt "#70146" msgid "Add to video library" -msgstr "Aggiungi alla Videoteca" +msgstr "Aggiungi alla videoteca" msgctxt "#70147" msgid "Video library (update TV show)" @@ -5180,8 +5184,8 @@ msgid "Remove" msgstr "Rimuovi" msgctxt "#70600" -msgid "Add Season" -msgstr "Aggiungi Stagione" +msgid "Add season" +msgstr "Aggiungi stagione" msgctxt "#70601" msgid "Update from the Internet:" @@ -6011,6 +6015,10 @@ msgctxt "#70806" msgid "Changing this parameter permanently overwrites the Elementum settings.\nDo you want to continue?" msgstr "Modificando questo parametro vengono sovrascritte permanentemente le impostazioni di Elementum.\nVuoi continuare?" +msgctxt "#70807" +msgid "Elementum does not support network folder downloads, do you want to change the download location?" +msgstr "Elementum non supporta i download su cartella di rete, vuoi cambiare il percorso di download?" + # DNS start [ settings and declaration ] msgctxt "#707401" msgid "Enable DNS check alert" diff --git a/resources/skins/Default/720p/InfoWindow.xml b/resources/skins/Default/720p/InfoWindow.xml index 5c10d776..d971eff0 100644 --- a/resources/skins/Default/720p/InfoWindow.xml +++ b/resources/skins/Default/720p/InfoWindow.xml @@ -57,6 +57,7 @@ <width>349</width> <height>500</height> <texture></texture> + <aspectratio>keep</aspectratio> <animation type="WindowOpen" reversible="false"> <effect type="slide" start="200,0" end="0,0" delay="300" tween="cubic" time="200" /> <effect type="fade" delay="300" end="100" time="240" /> diff --git a/servers/hdmario.json b/servers/hdmario.json new file mode 100644 index 00000000..17a614a8 --- /dev/null +++ b/servers/hdmario.json @@ -0,0 +1,42 @@ +{ + "active": false, + "find_videos": { + "ignore_urls": [], + "patterns": [ + { + "pattern": "https?://hdmario.live/embed/([0-9]+)", + "url": "https://hdmario.live/embed/\\1?" + } + ] + }, + "free": true, + "id": "hdmario", + "name": "HDmario", + "settings": [ + { + "default": false, + "enabled": true, + "id": "black_list", + "label": "@60654", + "type": "bool", + "visible": true + }, + { + "default": 0, + "enabled": true, + "id": "favorites_servers_list", + "label": "@60655", + "lvalues": [ + "No", + "1", + "2", + "3", + "4", + "5" + ], + "type": "list", + "visible": false + } + ], + "thumbnail": "" +} diff --git a/servers/hdmario.py b/servers/hdmario.py new file mode 100644 index 00000000..9fef8692 --- /dev/null +++ b/servers/hdmario.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +from threading import Thread + +from core import httptools, scrapertools +from platformcode import logger, config +from BaseHTTPServer import BaseHTTPRequestHandler + +baseUrl = 'https://hdmario.live' + +def test_video_exists(page_url): + logger.info("(page_url='%s')" % page_url) + global data + data = httptools.downloadpage(page_url).data + if "the page you are looking for could not be found" in data: + return False, config.get_localized_string(70449) % "HDmario" + return True, "" + + +def get_video_url(page_url, premium=False, user="", password="", video_password=""): + logger.info("url=" + page_url) + global data + # p,a,c,k,e,d data -> xhr.setRequestHeader + global secureProof, server + secureProof = scrapertools.find_single_match(data, '\|(\w{22})\|') + logger.info('X-Secure-Proof=' + secureProof) + + from BaseHTTPServer import HTTPServer + server = HTTPServer(('localhost', 9017), GetHandler) + Thread(target=server.serve_forever).start() + + video_urls = [['.m3u8 [HDmario]', 'http://localhost:9017/master/' + page_url.split('/')[-1].replace('?', '')]] + + return video_urls + +def shutdown(): + import time + time.sleep(1) + server.shutdown() + +class GetHandler(BaseHTTPRequestHandler): + def do_GET(self): + global secureProof + data = httptools.downloadpage(baseUrl + self.path, headers=[['X-Secure-Proof', secureProof]]).data + self.send_response(200) + self.end_headers() + self.wfile.write(data) + Thread(target=shutdown).start() + return \ No newline at end of file diff --git a/servers/torrent.py b/servers/torrent.py index 416419e0..f7fc2bf5 100755 --- a/servers/torrent.py +++ b/servers/torrent.py @@ -73,13 +73,18 @@ def elementum_download(item): if elementum_setting: set_elementum(True) time.sleep(3) - TorrentName = match(item.url, patron=r'btih(?::|%3A)([^&%]+)', string=True).match - post = 'uri=%s&file=null&all=1' % urllib.quote_plus(item.url) - match(elementum_host + 'add', post=post, timeout=5, alfa_s=True, ignore_response_code=True) - while not filetools.isfile(filetools.join(elementum_setting.getSetting('torrents_path'), TorrentName + '.torrent')): - time.sleep(1) + if config.get_setting('downloadpath').startswith('smb'): + select = platformtools.dialog_yesno('Elementum', config.get_localized_string(70807)) + if select: + xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?eyJjaGFubmVsIjoic2hvcnRjdXRzIiwgImFjdGlvbiI6IlNldHRpbmdPblBvc2l0aW9uIiwgImNhdGVnb3J5Ijo2LCAic2V0dGluZyI6MX0=)") + else: + TorrentName = match(item.url, patron=r'btih(?::|%3A)([^&%]+)', string=True).match + post = 'uri=%s&file=null&all=1' % urllib.quote_plus(item.url) + match(elementum_host + 'add', post=post, timeout=5, alfa_s=True, ignore_response_code=True) + while not filetools.isfile(filetools.join(elementum_setting.getSetting('torrents_path'), TorrentName + '.torrent')): + time.sleep(1) - monitor_update(TorrentPath, TorrentName) + monitor_update(TorrentPath, TorrentName) def elementum_monitor(): diff --git a/service.py b/service.py index 99ef0f57..de18c897 100644 --- a/service.py +++ b/service.py @@ -256,6 +256,10 @@ def check_for_update(overwrite=True): item_dummy = Item() videolibrary.list_movies(item_dummy, silent=True) + if config.get_setting('trakt_sync'): + from core import trakt_tools + trakt_tools.update_all() + def viewmodeMonitor(): try: diff --git a/specials/nextep.py b/specials/nextep.py index 0c861221..b8f5945c 100644 --- a/specials/nextep.py +++ b/specials/nextep.py @@ -1,9 +1,12 @@ # -*- coding: utf-8 -*- -import xbmc, xbmcgui, os -from platformcode import config, platformtools, logger +import xbmc, xbmcgui +from platformcode import config, platformtools from time import time, sleep -from core import scrapertools from core import jsontools, filetools +from core.support import log +from core.item import Item +from platformcode.launcher import play_from_library + import sys if sys.version_info[0] >= 3: from concurrent import futures @@ -24,19 +27,18 @@ def check(item): def return_item(item): - logger.info() + log() with futures.ThreadPoolExecutor() as executor: future = executor.submit(next_ep, item) item = future.result() return item def run(item): - logger.info() + log() with futures.ThreadPoolExecutor() as executor: future = executor.submit(next_ep, item) item = future.result() if item.next_ep: - from platformcode.launcher import play_from_library return play_from_library(item) @@ -47,7 +49,7 @@ def videolibrary(item): def next_ep(item): - logger.info() + log() condition = config.get_setting('next_ep') item.next_ep = False item.show_server = True @@ -56,16 +58,14 @@ def next_ep(item): time_over = False time_limit = time() + 30 - time_steps = [20,30,40,50,60,70,80,90,100,110,120] time_setting = config.get_setting('next_ep_seconds') - TimeFromEnd = time_setting if time_setting > 10 else time_steps[time_setting] - + TimeFromEnd = time_setting # wait until the video plays while not platformtools.is_playing() and time() < time_limit: sleep(1) - while platformtools.is_playing() and time_over == False: + while platformtools.is_playing() and not time_over: try: Total = xbmc.Player().getTotalTime() Actual = xbmc.Player().getTime() @@ -78,11 +78,11 @@ def next_ep(item): if time_over: if condition == 1: # hide server afther x second item.show_server = False - elif condition == 2: # play next fileif exist + elif condition == 2: # play next file if exist - # check i next file exist - current_filename = os.path.basename(item.strm_path) - base_path = os.path.basename(os.path.normpath(os.path.dirname(item.strm_path))) + # check if next file exist + current_filename = filetools.basename(item.strm_path) + base_path = filetools.basename(filetools.dirname(item.strm_path)) path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"),base_path) fileList = [] for file in filetools.listdir(path): @@ -96,11 +96,10 @@ def next_ep(item): next_file = None else: next_file = fileList[nextIndex] - logger.info('NEXTFILE' + next_file) + log('Next File:', next_file) # start next episode window afther x time if next_file: - from core.item import Item season_ep = next_file.split('.')[0] season = season_ep.split('x')[0] episode = season_ep.split('x')[1] @@ -111,13 +110,13 @@ def next_ep(item): contentEpisodeNumber= episode, contentSeason= season, contentTitle= next_ep, - contentType= 'tvshow', - infoLabels= {'episode': episode, 'mediatype': 'tvshow', 'season': season, 'title': next_ep}, + contentType= 'episode', + infoLabels= {'episode': episode, 'mediatype': 'episode', 'season': season, 'title': next_ep}, strm_path= filetools.join(base_path, next_file)) global INFO INFO = filetools.join(path, next_file.replace("strm", "nfo")) - logger.info('NEXTINFO' + INFO) + log('Next Info:',INFO) nextDialog = NextDialog(ND, config.get_runtime_path()) nextDialog.show() @@ -126,7 +125,7 @@ def next_ep(item): pass nextDialog.close() - logger.info('Next Episode: ' +str(nextDialog.stillwatching)) + log('Next Episode:', nextDialog.stillwatching) if nextDialog.stillwatching or nextDialog.continuewatching: item.next_ep = True @@ -135,7 +134,6 @@ def next_ep(item): sleep(1) xbmc.executebuiltin('Action(Back)') sleep(0.5) - from platformcode.launcher import play_from_library return play_from_library(item) else: item.show_server = False @@ -155,7 +153,7 @@ class NextDialog(xbmcgui.WindowXMLDialog): continuewatching = True def __init__(self, *args, **kwargs): - logger.info() + log() self.action_exitkeys_id = [xbmcgui.ACTION_STOP, xbmcgui.ACTION_BACKSPACE, xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK] self.progress_control = None @@ -203,7 +201,7 @@ class NextDialog(xbmcgui.WindowXMLDialog): self.close() def onAction(self, action): - logger.info() + log() if action in self.action_exitkeys_id: self.set_continue_watching(False) self.close() diff --git a/specials/videolibrary.py b/specials/videolibrary.py index 556faa00..86cd217f 100644 --- a/specials/videolibrary.py +++ b/specials/videolibrary.py @@ -181,6 +181,7 @@ def list_tvshows(item): itemlist = [] dead_list = [] zombie_list = [] + lista = [] # Obtenemos todos los tvshow.nfo de la videoteca de SERIES recursivamente for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.TVSHOWS_PATH): for s in subcarpetas: @@ -280,6 +281,7 @@ def list_tvshows(item): else: texto_update = config.get_localized_string(60023) value = 1 + item_tvshow.title += " [B]" + u"\u2022".encode('utf-8') + "[/B]" # item_tvshow.text_color = "0xFFDF7401" # Menu contextual: Eliminar serie/canal @@ -323,8 +325,7 @@ def list_tvshows(item): ## verifica la existencia de los canales ## if len(item_tvshow.library_urls) > 0: itemlist.append(item_tvshow) - - + lista.append({'title':item_tvshow.contentTitle,'thumbnail':item_tvshow.thumbnail,'fanart':item_tvshow.fanart, 'active': value, 'nfo':tvshow_path}) if itemlist: itemlist = sorted(itemlist, key=lambda it: it.title.lower()) @@ -332,8 +333,44 @@ def list_tvshows(item): itemlist.append(Item(channel=item.channel, action="update_videolibrary", thumbnail=item.thumbnail, title=typo(config.get_localized_string(70269), 'bold color kod'), folder=False)) + itemlist.append(Item(channel=item.channel, action="configure_update_videolibrary", thumbnail=item.thumbnail, + title=typo(config.get_localized_string(60599), 'bold color kod'), lista=lista, folder=False)) + return itemlist +def configure_update_videolibrary(item): + import xbmcgui + # Load list of options (active user channels that allow global search) + lista = [] + ids = [] + preselect = [] + + for i, item_tvshow in enumerate(item.lista): + it = xbmcgui.ListItem(item_tvshow["title"], '') + it.setArt({'thumb': item_tvshow["thumbnail"], 'fanart': item_tvshow["fanart"]}) + lista.append(it) + ids.append(Item(nfo=item_tvshow['nfo'])) + if item_tvshow['active']<=0: + preselect.append(i) + + # Dialog to select + ret = xbmcgui.Dialog().multiselect(config.get_localized_string(60601), lista, preselect=preselect, useDetails=True) + if ret < 0: + return False # order cancel + seleccionados = [ids[i] for i in ret] + + for tvshow in ids: + if tvshow not in seleccionados: + tvshow.active = 0 + elif tvshow in seleccionados: + tvshow.active = 1 + mark_tvshow_as_updatable(tvshow, silent=True) + + platformtools.itemlist_refresh() + + return True + + def get_seasons(item): logger.info() @@ -1076,13 +1113,14 @@ def mark_season_as_watched(item): platformtools.itemlist_refresh() -def mark_tvshow_as_updatable(item): +def mark_tvshow_as_updatable(item, silent=False): logger.info() head_nfo, it = videolibrarytools.read_nfo(item.nfo) it.active = item.active filetools.write(item.nfo, head_nfo + it.tojson()) - platformtools.itemlist_refresh() + if not silent: + platformtools.itemlist_refresh() def delete(item):