KoD 1.0.1

- 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
This commit is contained in:
marco
2020-05-22 19:27:16 +02:00
parent b73e3156fb
commit 96918d58ca
33 changed files with 585 additions and 459 deletions
+5 -5
View File
@@ -1,4 +1,4 @@
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.0" provider-name="KoD Team"> <addon id="plugin.video.kod" name="Kodi on Demand" version="1.0.1" provider-name="KoD Team">
<requires> <requires>
<!-- <import addon="script.module.libtorrent" optional="true"/> --> <!-- <import addon="script.module.libtorrent" optional="true"/> -->
<import addon="metadata.themoviedb.org"/> <import addon="metadata.themoviedb.org"/>
@@ -18,10 +18,10 @@
<screenshot>resources/media/themes/ss/2.png</screenshot> <screenshot>resources/media/themes/ss/2.png</screenshot>
<screenshot>resources/media/themes/ss/3.png</screenshot> <screenshot>resources/media/themes/ss/3.png</screenshot>
</assets> </assets>
<news>- completato il supporto ai torrent e aggiunto ilcorsaronero.xyz <news> - Fix Trakt e aggiuntoi i segni di spunta (già visto) nei canali
- aggiunto supporto agli episodi locali, ovvero poter inserire nella libreria di kodi un misto tra puntate &quot;di kod&quot; e file scaricati altrove - Fix Segna come già visto
- 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 - Aggiunta Disattivazione aggiornamento serie tramite multiselect
- ripensato il menu rapido, che ora è &quot;più rapido&quot;, ridisegnate alcune finestre</news> - Altri fix e migliorie</news>
<description lang="it">Naviga velocemente sul web e guarda i contenuti presenti</description> <description lang="it">Naviga velocemente sul web e guarda i contenuti presenti</description>
<disclaimer>[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] <disclaimer>[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]</disclaimer> [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]</disclaimer>
+3 -4
View File
@@ -1,6 +1,6 @@
{ {
"altadefinizione01": "https://altadefinizione01.photo", "altadefinizione01": "https://altadefinizione01.photo",
"altadefinizione01_link": "https://altadefinizione01.gallery", "altadefinizione01_link": "https://altadefinizione01.baby",
"altadefinizioneclick": "https://altadefinizione.family", "altadefinizioneclick": "https://altadefinizione.family",
"animeforce": "https://ww1.animeforce.org", "animeforce": "https://ww1.animeforce.org",
"animeleggendari": "https://animepertutti.org", "animeleggendari": "https://animepertutti.org",
@@ -12,7 +12,7 @@
"animeworld": "https://www.animeworld.tv", "animeworld": "https://www.animeworld.tv",
"casacinema": "https://www.casacinema.digital", "casacinema": "https://www.casacinema.digital",
"casacinemaInfo": "https://casacinema.life", "casacinemaInfo": "https://casacinema.life",
"cb01anime": "https://www.cineblog01.network/", "cb01anime": "https://www.cineblog01.red/",
"cinemalibero": "https://cinemalibero.plus", "cinemalibero": "https://cinemalibero.plus",
"cinetecadibologna": "http://cinestore.cinetecadibologna.it", "cinetecadibologna": "http://cinestore.cinetecadibologna.it",
"dreamsub": "https://dreamsub.stream", "dreamsub": "https://dreamsub.stream",
@@ -20,7 +20,7 @@
"fastsubita": "https://fastsubita.online", "fastsubita": "https://fastsubita.online",
"filmgratis": "https://www.filmaltadefinizione.tv", "filmgratis": "https://www.filmaltadefinizione.tv",
"filmigratis": "https://filmigratis.org", "filmigratis": "https://filmigratis.org",
"filmsenzalimiticc": "https://www.filmsenzalimiti.estate", "filmsenzalimiticc": "https://www.filmsenzalimiti.tel",
"filmstreaming01": "https://filmstreaming01.com", "filmstreaming01": "https://filmstreaming01.com",
"guardaserie_stream": "https://guardaserie.store", "guardaserie_stream": "https://guardaserie.store",
"guardaserieclick": "https://www.guardaserie.style", "guardaserieclick": "https://www.guardaserie.style",
@@ -28,7 +28,6 @@
"ilgeniodellostreaming": "https://ilgeniodellostreaming.tw", "ilgeniodellostreaming": "https://ilgeniodellostreaming.tw",
"italiaserie": "https://italiaserie.org", "italiaserie": "https://italiaserie.org",
"mondoserietv": "https://mondoserietv.com", "mondoserietv": "https://mondoserietv.com",
"netfreex": "https://www.netfreex.club",
"piratestreaming": "https://www.piratestreaming.biz", "piratestreaming": "https://www.piratestreaming.biz",
"polpotv": "https://polpotv.club", "polpotv": "https://polpotv.club",
"pufimovies": "https://pufimovies.com", "pufimovies": "https://pufimovies.com",
+2 -2
View File
@@ -138,5 +138,5 @@ def findvideos(item):
support.log('findvideos', item) support.log('findvideos', item)
return support.hdpass_get_servers(item) return support.hdpass_get_servers(item)
# def play(item): def play(item):
# return support.hdpass_get_url(item) return support.hdpass_get_url(item)
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "animesubita", "id": "animesubita",
"name": "AnimeSubIta", "name": "AnimeSubIta",
"active": true, "active": false,
"language": ["sub-ita"], "language": ["sub-ita"],
"thumbnail": "animesubita.png", "thumbnail": "animesubita.png",
"bannermenu": "animesubita.png", "bannermenu": "animesubita.png",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "animetubeita", "id": "animetubeita",
"name": "AnimeTubeITA", "name": "AnimeTubeITA",
"active": true, "active": false,
"language": ["sub-ita"], "language": ["sub-ita"],
"thumbnail": "animetubeita.png", "thumbnail": "animetubeita.png",
"bannermenu": "animetubeita.png", "bannermenu": "animetubeita.png",
+2
View File
@@ -166,6 +166,8 @@ def findvideos(item):
url=url, url=url,
server='directo', server='directo',
fulltitle=item.fulltitle, fulltitle=item.fulltitle,
contentSerieName=item.contentSerieName,
contentTitle=item.contentTitle,
show=item.show, show=item.show,
contentType=item.contentType, contentType=item.contentType,
folder=False)) folder=False))
+3
View File
@@ -126,3 +126,6 @@ def newest(categoria):
def findvideos(item): def findvideos(item):
support.log('findvideos ->', item) support.log('findvideos ->', item)
return support.hdpass_get_servers(item) return support.hdpass_get_servers(item)
def play(item):
return support.hdpass_get_url(item)
+1 -1
View File
@@ -137,7 +137,7 @@ def findvideos(item):
language = 'ITA' language = 'ITA'
if 'sub' in lang.lower(): if 'sub' in lang.lower():
language = 'Sub-' + language language = 'Sub-' + language
quality = url.split('/')[-1] quality = url.split('/')[-1].split('?')[0]
itemlist.append( itemlist.append(
support.Item(channel=item.channel, support.Item(channel=item.channel,
+13 -59
View File
@@ -3,16 +3,8 @@
# Canale per Eurostreaming # Canale per Eurostreaming
# by Greko # 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): from core import httptools, support
- serie, anime
"""
import re
from core import scrapertools, httptools, support
from core.item import Item from core.item import Item
def findhost(): def findhost():
@@ -24,7 +16,6 @@ host = support.config.get_channel_url(findhost)
headers = [['Referer', host]] headers = [['Referer', host]]
list_servers = ['akstream', 'wstream', 'mixdrop', 'vidtome', 'turbovid', 'speedvideo', 'flashx', 'nowvideo', 'deltabit'] list_servers = ['akstream', 'wstream', 'mixdrop', 'vidtome', 'turbovid', 'speedvideo', 'flashx', 'nowvideo', 'deltabit']
list_quality = ['default'] list_quality = ['default']
@@ -33,14 +24,10 @@ def mainlist(item):
support.log() support.log()
tvshow = ['' tvshow = []
] anime = ['/category/anime-cartoni-animati/']
anime = ['/category/anime-cartoni-animati/' mix = [('Aggiornamenti bullet bold {TV}', ['/aggiornamento-episodi/', 'peliculas', 'newest']),
] ('Archivio bullet bold {TV}', ['/category/serie-tv-archive/', 'peliculas'])]
mix = [
(support.typo('Aggiornamenti Serie-Anime', 'bullet bold'), ['/aggiornamento-episodi/', 'peliculas', 'newest']),
(support.typo('Archivio Serie-Anime', 'bullet bold'), ['/category/serie-tv-archive/', 'peliculas'])
]
search = '' search = ''
return locals() return locals()
@@ -48,64 +35,32 @@ def mainlist(item):
@support.scrape @support.scrape
def peliculas(item): def peliculas(item):
support.log()
#findhost()
action = 'episodios' action = 'episodios'
if item.args == 'newest': if item.args == 'newest':
patron = r'<span class="serieTitle" style="font-size:20px">(?P<title>.*?)[^–â][\s]*<a href="(?P<url>[^"]+)"[^>]*> ?(?P<episode>\d+x\d+-\d+|\d+x\d+) .*?[ ]?\(?(?P<lang>SUB ITA)?\)?</a>' patron = r'<span class="serieTitle" style="font-size:20px">(?P<title>.*?)[^–â][\s]*<a href="(?P<url>[^"]+)"[^>]*> ?(?P<episode>\d+x\d+-\d+|\d+x\d+) .*?[ ]?\(?(?P<lang>SUB ITA)?\)?</a>'
pagination = '' pagination = ''
else: 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>' 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 &raquo;</a>' patronNext=r'a class="next page-numbers" href="?([^>"]+)">Avanti &raquo;</a>'
# debug = True
return locals() return locals()
@support.scrape @support.scrape
def episodios(item): def episodios(item):
support.log("episodios: %s" % item) data = support.match(item, headers=headers).data
#findhost() 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
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>'
patronBlock = r'</span>(?P<block>[a-zA-Z\s]+\d+(.+?)?(?:\()?(?P<lang>ITA|SUB ITA)(?:\))?.*?)</div></div>' 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'(?P<season>\d+)&#\d+;(?P<episode>\d+(?:-\d+)?)\s*(?:</strong>|<em>)?\s*(?P<title>.+?)(?:–|-.+?-|–.+?–|–|em|.)?(?:/em.*?)?(?:<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 />'
def itemHook(item): def itemHook(item):
if not item.url: if not item.url:
item.title += ' [B][COLOR red]### NO LINK ###[/COLOR][/B]' item.url =''
return item return item
#support.regexDbg(item, patronBlock, headers, data)
#debug = True
return locals() 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): def search(item, texto):
support.log() support.log()
@@ -122,7 +77,6 @@ def search(item, texto):
support.log(line) support.log(line)
return [] return []
# =========== def novità in ricerca globale =============
def newest(categoria): def newest(categoria):
support.log() support.log()
@@ -144,7 +98,7 @@ def newest(categoria):
return itemlist return itemlist
# =========== def findvideos =============
def findvideos(item): def findvideos(item):
support.log('findvideos', item) support.log()
return support.server(item, item.url) return support.server(item, item.url)
+2 -2
View File
@@ -93,5 +93,5 @@ def search(item, text):
def findvideos(item): def findvideos(item):
if item.contentType == 'tvshow': item.contentType = 'episode' if item.contentType == 'tvshow': item.contentType = 'episode'
video_library = True if 'movie' in item.args else False Videolibrary = True if 'movie' in item.args else False
return support.server(item, support.match(item.url, patron=r'"(magnet[^"]+)').match, video_library=video_library) return support.server(item, support.match(item.url, patron=r'"(magnet[^"]+)').match, Videolibrary=Videolibrary)
+1 -1
View File
@@ -50,7 +50,7 @@ def peliculas(item):
def findvideos(item): def findvideos(item):
return support.server(item, video_library=False) return support.server(item, Videolibrary=False)
def search(item, text): def search(item, text):
+4 -1
View File
@@ -7,7 +7,10 @@ from core import support
from core.item import Item from core.item import Item
from platformcode import logger, config 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 = "" headers = ""
IDIOMAS = {'Italiano': 'IT'} IDIOMAS = {'Italiano': 'IT'}
+1 -1
View File
@@ -292,7 +292,7 @@ def findvideos(item):
itemlist.append(support.Item(channel = item.channel, server = 'directo', title = 'Diretto', fulltitle = item.fulltitle, 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' )) 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): def getUrl(pathId):
+3
View File
@@ -143,3 +143,6 @@ def findvideos(item):
matches = support.match(url,patron=r'<a href="([^"]+)">(\d+)<', patronBlock=r'<h3>EPISODIO</h3><ul>(.*?)</ul>').matches 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]) if matches: item.url = support.urlparse.urljoin(url, matches[-1][0])
return support.hdpass_get_servers(item) return support.hdpass_get_servers(item)
def play(item):
return support.hdpass_get_url(item)
+1 -1
View File
@@ -209,7 +209,7 @@ def findvideos(item):
url= 'https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/' + url, url= 'https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/' + url,
server= 'directo') 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): def make_itemlist(itemlist, item, data):
search = item.search if item.search else '' search = item.search if item.search else ''
+44 -19
View File
@@ -19,9 +19,7 @@ else:
from future.builtins import range from future.builtins import range
from past.utils import old_div from past.utils import old_div
import datetime
import re import re
import time
from core import filetools from core import filetools
from core import httptools from core import httptools
@@ -32,6 +30,7 @@ from platformcode import platformtools
from lib import unshortenit from lib import unshortenit
dict_servers_parameters = {} dict_servers_parameters = {}
server_list = {}
def find_video_items(item=None, data=None): def find_video_items(item=None, data=None):
@@ -154,8 +153,6 @@ def findvideos(data, skip=False):
servers_list = list(get_servers_list().keys()) servers_list = list(get_servers_list().keys())
# Ordenar segun favoriteslist si es necesario
servers_list = sort_servers(servers_list)
is_filter_servers = False is_filter_servers = False
# Ejecuta el findvideos en cada servidor activo # Ejecuta el findvideos en cada servidor activo
@@ -211,13 +208,43 @@ def guess_server_thumbnail(serverid):
def get_server_from_url(url): def get_server_from_url(url):
encontrado = findvideos(url, True) logger.info()
if len(encontrado) > 0: servers_list = list(get_servers_list().keys())
devuelve = encontrado[0][2]
else:
devuelve = "directo"
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): 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. y como valor un diccionario con los parametros del servidor.
@rtype: dict @rtype: dict
""" """
server_list = {} global server_list
for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers")): if not server_list:
if server.endswith(".json") and not server == "version.json": for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers")):
server_parameters = get_server_parameters(server) if server.endswith(".json") and not server == "version.json":
server_list[server.split(".")[0]] = server_parameters server_parameters = get_server_parameters(server)
server_list[server.split(".")[0]] = server_parameters
server_list = sort_servers(server_list)
return server_list return server_list
@@ -725,9 +753,6 @@ def filter_servers(servers_list):
config.get_localized_string(70281)): config.get_localized_string(70281)):
servers_list = servers_list_filter servers_list = servers_list_filter
if config.get_setting("favorites_servers") == True:
servers_list = sort_servers(servers_list)
return servers_list return servers_list
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+93 -80
View File
@@ -37,25 +37,22 @@ def hdpass_get_servers(item):
page = httptools.downloadpage(url, CF=False).data page = httptools.downloadpage(url, CF=False).data
mir = scrapertools.find_single_match(page, patron_mir) mir = scrapertools.find_single_match(page, patron_mir)
with futures.ThreadPoolExecutor() as executor: for mir_url, srv in scrapertools.find_multiple_matches(mir, patron_option):
thL = [] mir_url = scrapertools.decodeHtmlentities(mir_url)
for mir_url, srv in scrapertools.find_multiple_matches(mir, patron_option): log(mir_url)
mir_url = scrapertools.decodeHtmlentities(mir_url) it = Item(channel=item.channel,
log(mir_url) action="play",
it = Item(channel=item.channel, fulltitle=item.fulltitle,
action="play", quality=quality,
fulltitle=item.fulltitle, show=item.show,
quality=quality, thumbnail=item.thumbnail,
show=item.show, contentType=item.contentType,
thumbnail=item.thumbnail, title=srv,
contentType=item.contentType, server=srv,
title=srv, url= mir_url)
# server=srv, if not servertools.get_server_parameters(srv.lower()): # do not exists or it's empty
url= mir_url) it = hdpass_get_url(it)[0]
thL.append(executor.submit(hdpass_get_url, it)) ret.append(it)
for res in futures.as_completed(thL):
if res.result():
ret.append(res.result()[0])
return ret return ret
# Carica la pagina # Carica la pagina
itemlist = [] itemlist = []
@@ -217,8 +214,12 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
if scraped['season']: if scraped['season']:
stagione = 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) episode = str(int(scraped['season'])) +'x'+ str(int(scraped['episode'])).zfill(2)
elif item.season: 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'] episode = item.season +'x'+ scraped['episode']
elif item.contentType == 'tvshow' and (scraped['episode'] == '' and scraped['season'] == '' and stagione == ''): elif item.contentType == 'tvshow' and (scraped['episode'] == '' and scraped['season'] == '' and stagione == ''):
item.news = 'season_completed' item.news = 'season_completed'
@@ -228,6 +229,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
if 'x' in episode: if 'x' in episode:
ep = episode.split('x') ep = episode.split('x')
episode = str(int(ep[0])).zfill(1) + 'x' + str(int(ep[1])).zfill(2) 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+)') 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) 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"]: if item.infoLabels["title"] == scraped["title"]:
infolabels = item.infoLabels infolabels = item.infoLabels
else: else:
infolabels = {} if function == 'episodios':
infolabels = item.infoLabels
else:
infolabels = {}
if scraped['year']: if scraped['year']:
infolabels['year'] = scraped['year'] infolabels['year'] = scraped['year']
if scraped["plot"]: if scraped["plot"]:
infolabels['plot'] = plot infolabels['plot'] = plot
if scraped['duration']: if scraped['duration']:
matches = scrapertools.find_multiple_matches(scraped['duration'], matches = scrapertools.find_multiple_matches(scraped['duration'],r'([0-9])\s*?(?:[hH]|:|\.|,|\\|\/|\||\s)\s*?([0-9]+)')
r'([0-9])\s*?(?:[hH]|:|\.|,|\\|\/|\||\s)\s*?([0-9]+)')
for h, m in matches: for h, m in matches:
scraped['duration'] = int(h) * 60 + int(m) scraped['duration'] = int(h) * 60 + int(m)
if not matches: if not matches:
@@ -331,8 +336,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
infoLabels=infolabels, infoLabels=infolabels,
thumbnail=item.thumbnail if function == 'episodios' or not scraped["thumb"] else scraped["thumb"], thumbnail=item.thumbnail if function == 'episodios' or not scraped["thumb"] else scraped["thumb"],
args=item.args, 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 '', contentSerieName= item.contentSerieName if item.contentSerieName else title if 'movie' not in [item.contentType, CT] and function == 'episodios' else item.fulltitle,
contentTitle= title if item.contentType or CT == 'movie' else '', contentTitle=item.contentTitle if item.contentTitle else title if 'movie' in [item.contentType, CT] else '',
contentLanguage = lang1, contentLanguage = lang1,
contentEpisodeNumber=episode if episode else '', contentEpisodeNumber=episode if episode else '',
news= item.news if item.news else '', news= item.news if item.news else '',
@@ -507,6 +512,10 @@ def scrape(func):
# itemlist = filterLang(item, itemlist) # causa problemi a newest # 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 itemlist
return wrapper return wrapper
@@ -1103,83 +1112,82 @@ def pagination(itemlist, item, page, perpage, function_level=1):
thumbnail=thumb())) thumbnail=thumb()))
return itemlist 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: if not data and not itemlist:
data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data
if data: if data:
itemList = servertools.find_video_items(data=str(data)) itemList = servertools.find_video_items(data=str(data))
itemlist = itemlist + itemList itemlist = itemlist + itemList
verifiedItemlist = [] verifiedItemlist = []
for videoitem in itemlist:
if not videoitem.server: def getItem(videoitem):
findS = servertools.findvideos(videoitem.url) if not servertools.get_server_parameters(videoitem.server.lower()): # do not exists or it's empty
if findS: findS = servertools.get_server_from_url(videoitem.url)
findS = findS[0] log(findS)
elif item.channel == 'community': if not findS:
findS= ('Diretto', videoitem.url, 'directo') if item.channel == 'community':
else: findS= ('Diretto', videoitem.url, 'directo')
videoitem.url = unshortenit.unshorten(videoitem.url)[0]
findS = servertools.findvideos(videoitem.url)
if findS:
findS = findS[0]
else: else:
log(videoitem, 'Non supportato') videoitem.url = unshortenit.unshorten_only(videoitem.url)[0]
continue findS = servertools.get_server_from_url(videoitem.url)
if not findS:
log(videoitem, 'Non supportato')
return
videoitem.server = findS[2] videoitem.server = findS[2]
videoitem.title = findS[0] videoitem.title = findS[0]
videoitem.url = findS[1] 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 '') 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.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.fulltitle = item.fulltitle
videoitem.show = item.show videoitem.show = item.show
videoitem.thumbnail = item.thumbnail videoitem.thumbnail = item.thumbnail
videoitem.channel = item.channel
videoitem.contentType = item.contentType videoitem.contentType = item.contentType
videoitem.infoLabels = item.infoLabels 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: if patronTag:
addQualityTag(item, verifiedItemlist, data, 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): # Auto Play & Hide Links
from core import jsontools
from platformcode.config import get_setting
CL = get_setting('checklinks') or get_setting('checklinks', item.channel)
AP, HS = autoplay.get_channel_AP_HS(item) AP, HS = autoplay.get_channel_AP_HS(item)
if CL and not AP: # Check Links
if get_setting('checklinks', item.channel): if not AP and (config.get_setting('checklinks') or config.get_setting('checklinks', item.channel)):
checklinks = get_setting('checklinks', item.channel) if config.get_setting('checklinks', item.channel):
checklinks_number = get_setting('checklinks_number', item.channel) checklinks_number = config.get_setting('checklinks_number', item.channel)
else: elif config.get_setting('checklinks'):
checklinks = get_setting('checklinks') checklinks_number = config.get_setting('checklinks_number')
checklinks_number = get_setting('checklinks_number') verifiedItemlist = servertools.check_list_links(verifiedItemlist, checklinks_number)
itemlist = servertools.check_list_links(itemlist, checklinks_number)
if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1]: 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(itemlist, item) autoplay.start(verifiedItemlist, item)
if item.contentChannel != 'videolibrary' and video_library: videolibrary(itemlist, item, function_level=3) if Videolibrary and item.contentChannel != 'videolibrary':
if down_load == True: download(itemlist, item, function_level=3) 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): def filterLang(item, itemlist):
# import channeltools # import channeltools
@@ -1197,14 +1205,16 @@ def aplay(item, itemlist, list_servers='', list_quality=''):
autoplay.start(itemlist, item) autoplay.start(itemlist, item)
def log(stringa1="", stringa2="", stringa3="", stringa4="", stringa5=""): def log(*args):
# Function to simplify the log # Function to simplify the log
# Automatically returns File Name and Function Name # Automatically returns File Name and Function Name
string = ''
for arg in args:
string += ' '+str(arg)
frame = inspect.stack()[1] frame = inspect.stack()[1]
filename = frame[0].f_code.co_filename filename = frame[0].f_code.co_filename
filename = os.path.basename(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): def channel_config(item, itemlist):
@@ -1302,9 +1312,12 @@ def addQualityTag(item, itemlist, data, patron):
def get_jwplayer_mediaurl(data, srvName): def get_jwplayer_mediaurl(data, srvName):
video_urls = [] video_urls = []
block = scrapertools.find_single_match(data, r'sources: \[([^\]]+)\]') block = scrapertools.find_single_match(data, r'sources: \[([^\]]+)\]')
sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?') if 'file:' in block:
if not sources: 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*"([^"]+)"') sources = scrapertools.find_multiple_matches(data, r'src:\s*"([^"]+)",\s*type:\s*"[^"]+",[^,]+,\s*label:\s*"([^"]+)"')
else:
sources =[(block.replace('"',''), '')]
for url, quality in sources: for url, quality in sources:
quality = 'auto' if not quality else quality quality = 'auto' if not quality else quality
if url.split('.')[-1] != 'mpd': if url.split('.')[-1] != 'mpd':
+1 -1
View File
@@ -984,7 +984,7 @@ class Tmdb(object):
url += '&year=%s' % self.busqueda_year url += '&year=%s' % self.busqueda_year
buscando = self.busqueda_texto.capitalize() 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) resultado = self.get_json(url)
if not isinstance(resultado, dict): if not isinstance(resultado, dict):
resultado = ast.literal_eval(resultado.decode('utf-8')) resultado = ast.literal_eval(resultado.decode('utf-8'))
+27 -44
View File
@@ -8,6 +8,9 @@ from core import httptools, jsontools
from core.item import Item from core.item import Item
from platformcode import config, logger from platformcode import config, logger
from threading import Thread 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_id = "502bd1660b833c1ae69828163c0848e84e9850061e5529f30930e7356cae73b1"
client_secret = "1d30d5b24acf223a5e1ab6c61d08b69992d98ed5b0c7e26b052b5e6a592035a4" client_secret = "1d30d5b24acf223a5e1ab6c61d08b69992d98ed5b0c7e26b052b5e6a592035a4"
@@ -196,58 +199,37 @@ def get_trakt_watched(id_type, mediatype, update=False):
def trakt_check(itemlist): def trakt_check(itemlist):
from core.support import typo def sync(item, id_result):
id_result = '' info = item.infoLabels
# check = u'\u221a' try:
check = typo(u'\u221a','[] color kod bold')+' ' if info['mediatype'] == 'movie' and info['tmdb_id'] in id_result[info['mediatype']]:
synced = False item.infoLabels['playcount'] = 1
try: elif info['mediatype'] == 'episode' and info['tmdb_id'] in id_result[info['mediatype']]:
for item in itemlist: id = info['tmdb_id']
info = item.infoLabels 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: id_result = {}
get_sync_from_file() id_result['movie'] = get_trakt_watched('tmdb', 'movies', True)
synced = True id_result['episode'] = get_trakt_watched('tmdb', 'shows', True)
mediatype = 'movies' with futures.ThreadPoolExecutor() as executor:
id_type = 'tmdb' [executor.submit(sync, it, id_result) for it in itemlist]
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
return itemlist return itemlist
def get_sync_from_file(): def get_sync_from_file():
logger.info() 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 = {} trakt_node = {}
if os.path.exists(sync_path): if os.path.exists(sync_path):
trakt_node = jsontools.get_node_from_file('trakt', "TRAKT") 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): def update_trakt_data(mediatype, trakt_data):
logger.info() 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): if os.path.exists(sync_path):
trakt_node = jsontools.get_node_from_file('trakt', "TRAKT") trakt_node = jsontools.get_node_from_file('trakt', "TRAKT")
trakt_node[mediatype] = trakt_data trakt_node[mediatype] = trakt_data
@@ -289,6 +271,7 @@ def wait_for_update_trakt():
t.isAlive() t.isAlive()
def update_all(): def update_all():
# from core.support import dbg;dbg()
from time import sleep from time import sleep
logger.info() logger.info()
sleep(20) sleep(20)
+130 -141
View File
@@ -2,14 +2,12 @@
# ------------------------------------------------------------ # ------------------------------------------------------------
# tvdb # tvdb
# ------------------------------------------------------------ # ------------------------------------------------------------
# Scraper para el site thetvdb.com usando API v2.1 # Scraper for thetvdb.com using API v2.1
# Utilizado para obtener datos de series para la videoteca # Used to obtain series data for the video library
# del addon y también Kodi.
# ------------------------------------------------------------ # ------------------------------------------------------------
from future import standard_library from future import standard_library
standard_library.install_aliases() standard_library.install_aliases()
#from builtins import str
from future.builtins import object from future.builtins import object
import urllib.request, urllib.error, urllib.parse import urllib.request, urllib.error, urllib.parse
@@ -35,41 +33,41 @@ DEFAULT_HEADERS = {
'Authorization': 'Bearer ' + TOKEN, 'Authorization': 'Bearer ' + TOKEN,
} }
# Traducciones - Inicio # # Traducciones - Inicio
DICT_STATUS = {'Continuing': 'En emisión', 'Ended': 'Finalizada'} # DICT_STATUS = {'Continuing': 'En emisión', 'Ended': 'Finalizada'}
DICT_GENRE = { # DICT_GENRE = {
'Action': 'Acción', # 'Action': 'Acción',
'Adventure': 'Aventura', # 'Adventure': 'Aventura',
'Animation': 'Animación', # 'Animation': 'Animación',
'Children': 'Niños', # 'Children': 'Niños',
'Comedy': 'Comedia', # 'Comedy': 'Comedia',
'Crime': 'Crimen', # 'Crime': 'Crimen',
'Documentary': 'Documental', # 'Documentary': 'Documental',
# 'Drama': 'Drama', # # 'Drama': 'Drama',
'Family': 'Familiar', # 'Family': 'Familiar',
'Fantasy': 'Fantasía', # 'Fantasy': 'Fantasía',
'Food': 'Comida', # 'Food': 'Comida',
'Game Show': 'Concurso', # 'Game Show': 'Concurso',
'Home and Garden': 'Hogar y Jardín', # 'Home and Garden': 'Hogar y Jardín',
# 'Horror': 'Horror', 'Mini-Series': 'Mini-Series', # # 'Horror': 'Horror', 'Mini-Series': 'Mini-Series',
'Mystery': 'Misterio', # 'Mystery': 'Misterio',
'News': 'Noticias', # 'News': 'Noticias',
# 'Reality': 'Telerrealidad', # # 'Reality': 'Telerrealidad',
'Romance': 'Romántico', # 'Romance': 'Romántico',
'Science-Fiction': 'Ciencia-Ficción', # 'Science-Fiction': 'Ciencia-Ficción',
'Soap': 'Telenovela', # 'Soap': 'Telenovela',
# 'Special Interest': 'Special Interest', # # 'Special Interest': 'Special Interest',
'Sport': 'Deporte', # 'Sport': 'Deporte',
# 'Suspense': 'Suspense', # # 'Suspense': 'Suspense',
'Talk Show': 'Programa de Entrevistas', # 'Talk Show': 'Programa de Entrevistas',
# 'Thriller': 'Thriller', # # 'Thriller': 'Thriller',
'Travel': 'Viaje', # 'Travel': 'Viaje',
# 'Western': 'Western' # # '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', # 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-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'} # 'TV-14': 'Mayores de 14 años', 'TV-MA': 'Mayores de 17 años'}
# Traducciones - Fin # # Traducciones - Fin
otvdb_global = None otvdb_global = None
@@ -86,7 +84,7 @@ def find_and_set_infoLabels(item):
tvdb_result = None tvdb_result = None
title = item.contentSerieName 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}\))$") year = scrapertools.find_single_match(title, "^.+?\s*(\(\d{4}\))$")
if year: if year:
title = title.replace(year, "").strip() title = title.replace(year, "").strip()
@@ -104,24 +102,23 @@ def find_and_set_infoLabels(item):
if not item.contentSeason: if not item.contentSeason:
p_dialog.update(50, config.get_localized_string(60296), config.get_localized_string(60295)) p_dialog.update(50, config.get_localized_string(60296), config.get_localized_string(60295))
results, info_load = otvdb_global.get_list_results() results, info_load = otvdb_global.get_list_results()
logger.debug("results es %s" % results) logger.debug("results: %s" % results)
if not item.contentSeason: if not item.contentSeason:
p_dialog.update(100, config.get_localized_string(60296), config.get_localized_string(60297) % len(results)) p_dialog.update(100, config.get_localized_string(60296), config.get_localized_string(60297) % len(results))
p_dialog.close() p_dialog.close()
if len(results) > 1: if len(results) > 1:
tvdb_result = platformtools.show_video_info(results, item=item, scraper=Tvdb, tvdb_result = platformtools.show_video_info(results, item=item, scraper=Tvdb, caption=config.get_localized_string(60298) % title)
caption=config.get_localized_string(60298) % title)
elif len(results) > 0: elif len(results) > 0:
tvdb_result = results[0] tvdb_result = results[0]
# todo revisar # todo revisar
if isinstance(item.infoLabels, InfoLabels): if isinstance(item.infoLabels, InfoLabels):
logger.debug("es instancia de infoLabels") logger.debug("is an instance of infoLabels")
infoLabels = item.infoLabels infoLabels = item.infoLabels
else: else:
logger.debug("NO ES instancia de infoLabels") logger.debug("NOT an instance of infoLabels")
infoLabels = InfoLabels() infoLabels = InfoLabels()
if tvdb_result: if tvdb_result:
@@ -146,12 +143,9 @@ def find_and_set_infoLabels(item):
def set_infoLabels_item(item): def set_infoLabels_item(item):
""" """
Obtiene y fija (item.infoLabels) los datos extras de una serie, capitulo o pelicula. Gets and sets (item.infoLabels) the extra data of a series, chapter or movie.
@param item: Objeto que representa un pelicula, serie o capitulo. El atributo infoLabels sera modificado @param item: Object that represents a movie, series or chapter. The infoLabels attribute will be modified including the extra localized data.
incluyendo los datos extras localizados.
@type item: Item @type item: Item
""" """
global otvdb_global global otvdb_global
@@ -166,7 +160,7 @@ def set_infoLabels_item(item):
try: try:
int_season = int(item.infoLabels['season']) int_season = int(item.infoLabels['season'])
except ValueError: except ValueError:
logger.debug("El numero de temporada no es valido") logger.debug("The season number is not valid")
item.contentType = item.infoLabels['mediatype'] item.contentType = item.infoLabels['mediatype']
return -1 * len(item.infoLabels) return -1 * len(item.infoLabels)
@@ -184,12 +178,12 @@ def set_infoLabels_item(item):
try: try:
int_episode = int(item.infoLabels['episode']) int_episode = int(item.infoLabels['episode'])
except ValueError: 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'] item.contentType = item.infoLabels['mediatype']
return -1 * len(item.infoLabels) return -1 * len(item.infoLabels)
# Tenemos numero de temporada y numero de episodio validos... # We have a valid season number and episode number ...
# ... buscar datos episodio # ... search episode data
item.infoLabels['mediatype'] = 'episode' item.infoLabels['mediatype'] = 'episode'
lang = DEFAULT_LANG lang = DEFAULT_LANG
@@ -211,7 +205,7 @@ def set_infoLabels_item(item):
t.start() t.start()
l_hilo.append(t) l_hilo.append(t)
# esperar q todos los hilos terminen # wait for all the threads to end
for x in l_hilo: for x in l_hilo:
x.join() 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) 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: if data_episode:
item.infoLabels['title'] = data_episode['episodeName'] item.infoLabels['title'] = data_episode['episodeName']
# fix en casos que el campo desde la api era null--> None # 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]) l_castandrole.extend([(p, '') for p in guest_stars])
item.infoLabels['castandrole'] = l_castandrole item.infoLabels['castandrole'] = l_castandrole
# datos para nfo # data for nfo
item.season_id = data_episode["airedSeasonID"] item.season_id = data_episode["airedSeasonID"]
item.episode_id = data_episode["id"] item.episode_id = data_episode["id"]
return len(item.infoLabels) return len(item.infoLabels)
else: else:
# Tenemos numero de temporada valido pero no numero de episodio... # We have a valid season number but no episode number ...
# ... buscar datos temporada # ... search season data
item.infoLabels['mediatype'] = 'season' item.infoLabels['mediatype'] = 'season'
data_season = otvdb_global.get_images(otvdb_global.get_id(), "season", int_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'] item.thumbnail = HOST_IMAGE + data_season['image_season_%s' % int_season][0]['fileName']
return len(item.infoLabels) return len(item.infoLabels)
# Buscar... # Search...
else: 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']: 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']) 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']: elif not otvdb_global and item.infoLabels['zap2it_id']:
otvdb_global = Tvdb(zap2it_id=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: if otvdb_global is None:
otvdb_global = Tvdb(search=item.infoLabels['tvshowtitle']) otvdb_global = Tvdb(search=item.infoLabels['tvshowtitle'])
if otvdb_global and otvdb_global.get_id(): if otvdb_global and otvdb_global.get_id():
__leer_datos(otvdb_global) __leer_datos(otvdb_global)
# La busqueda ha encontrado un resultado valido # The search has found a valid result
return len(item.infoLabels) return len(item.infoLabels)
def get_nfo(item): 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 @type item: Item
@rtype: str @rtype: str
@return: @return:
""" """
if "season" in item.infoLabels and "episode" in item.infoLabels: if "season" in item.infoLabels and "episode" in item.infoLabels:
info_nfo = "http://thetvdb.com/?tab=episode&seriesid=%s&seasonid=%s&id=%s\n" \ info_nfo = "http://thetvdb.com/?tab=episode&seriesid=%s&seasonid=%s&id=%s\n" % (item.infoLabels['tvdb_id'], item.season_id, item.episode_id)
% (item.infoLabels['tvdb_id'], item.season_id, item.episode_id)
else: else:
info_nfo = ', '.join(item.infoLabels['url_scraper']) + "\n" info_nfo = ', '.join(item.infoLabels['url_scraper']) + "\n"
@@ -311,7 +304,7 @@ def get_nfo(item):
def completar_codigos(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 @param item: tipo item
@type item: Item @type item: Item
""" """
@@ -347,27 +340,25 @@ class Tvdb(object):
self.episodes = {} self.episodes = {}
if kwargs.get('tvdb_id', ''): if kwargs.get('tvdb_id', ''):
# Busqueda por identificador tvdb # Search by tvdb identifier
self.__get_by_id(kwargs.get('tvdb_id', '')) self.__get_by_id(kwargs.get('tvdb_id', ''))
if not self.list_results and config.get_setting("tvdb_retry_eng", "videolibrary"): if not self.list_results and config.get_setting("tvdb_retry_eng", "videolibrary"):
from platformcode import platformtools from platformcode import platformtools
platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, config.get_localized_string(60302), sound=False)
config.get_localized_string(60302), sound=False)
self.__get_by_id(kwargs.get('tvdb_id', ''), "en") self.__get_by_id(kwargs.get('tvdb_id', ''), "en")
self.lang = "en" self.lang = "en"
elif self.search_name: elif self.search_name:
# Busqueda por texto # BUsqueda by text
self.__search(kwargs.get('search', ''), kwargs.get('imdb_id', ''), kwargs.get('zap2it_id', '')) 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"): if not self.list_results and config.get_setting("tvdb_retry_eng", "videolibrary"):
from platformcode import platformtools from platformcode import platformtools
platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, platformtools.dialog_notification(config.get_localized_string(60299) % DEFAULT_LANG, config.get_localized_string(60302))
config.get_localized_string(60302))
self.__search(kwargs.get('search', ''), kwargs.get('imdb_id', ''), kwargs.get('zap2it_id', ''), "en") self.__search(kwargs.get('search', ''), kwargs.get('imdb_id', ''), kwargs.get('zap2it_id', ''), "en")
self.lang = "en" self.lang = "en"
if not self.result: if not self.result:
# No hay resultados de la busqueda # No search results
if kwargs.get('tvdb_id', ''): if kwargs.get('tvdb_id', ''):
buscando = kwargs.get('tvdb_id', '') buscando = kwargs.get('tvdb_id', '')
else: else:
@@ -381,12 +372,12 @@ class Tvdb(object):
if TOKEN == "": if TOKEN == "":
cls.__login() cls.__login()
else: 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 from time import gmtime, strftime
current_date = strftime("%Y-%m-%d", gmtime()) current_date = strftime("%Y-%m-%d", gmtime())
if config.get_setting("tvdb_token_date", "") != current_date: 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(): if cls.__refresh_token():
config.set_setting("tvdb_token_date", current_date) config.set_setting("tvdb_token_date", current_date)
@@ -408,7 +399,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) 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: else:
dict_html = jsontools.load(html) dict_html = jsontools.load(html)
@@ -435,8 +426,8 @@ class Tvdb(object):
response.close() response.close()
except urllib.error.HTTPError as err: except urllib.error.HTTPError as err:
logger.error("err.code es %s" % err.code) logger.error("err.code %s" % err.code)
# si hay error 401 es que el token se ha pasado de tiempo y tenemos que volver a llamar a login # 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: if err.code == 401:
cls.__login() cls.__login()
else: else:
@@ -444,7 +435,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) 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: else:
dict_html = jsontools.load(html) 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): def get_info_episode(self, _id, season=1, episode=1, lang=DEFAULT_LANG, id_episode=None):
""" """
Devuelve los datos de un episodio. Returns the data of an episode.
@param _id: identificador de la serie @param _id: series identifier
@type _id: str @type _id: str
@param season: numero de temporada [por defecto = 1] @param season: season number [default = 1]
@type season: int @type season: int
@param episode: numero de episodio [por defecto = 1] @param episode: episode number [default = 1]
@type episode: int @type episode: int
@param lang: codigo de idioma para buscar @param lang: language code to search
@type lang: str @type lang: str
@param id_episode: codigo del episodio. @param id_episode: episode code.
@type id_episode: int @type id_episode: int
@rtype: dict @rtype: dict
@return: @return:
@@ -541,7 +532,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) 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: else:
dict_html = jsontools.load(html) dict_html = jsontools.load(html)
@@ -552,10 +543,10 @@ class Tvdb(object):
def get_list_episodes(self, _id, page=1): def get_list_episodes(self, _id, page=1):
""" """
Devuelve el listado de episodios de una serie. Returns the list of episodes of a series.
@param _id: identificador de la serie @param _id: series identifier
@type _id: str @type _id: str
@param page: numero de pagina a buscar [por defecto = 1] @param page: page number to search [default = 1]
@type page: int @type page: int
@rtype: dict @rtype: dict
@return: @return:
@@ -604,7 +595,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) 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: else:
self.list_episodes[page] = jsontools.load(html) 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): def get_episode_by_id(self, _id, lang=DEFAULT_LANG, semaforo=None):
""" """
Obtiene los datos de un episodio Get the data of an episode
@param _id: identificador del episodio @param _id: episode identifier
@type _id: str @type _id: str
@param lang: código de idioma @param lang: language code
@param semaforo: semaforo para multihilos @param semaforo: semaphore for multihilos
@type semaforo: threading.Semaphore @type semaforo: threading.Semaphore
@type lang: str @type lang: str
@rtype: dict @rtype: dict
@@ -691,7 +682,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
# if isinstance(ex, urllib).HTTPError: # 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)) 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 en: %s" % message)
@@ -708,14 +699,14 @@ class Tvdb(object):
def __search(self, name, imdb_id, zap2it_id, lang=DEFAULT_LANG): def __search(self, name, imdb_id, zap2it_id, lang=DEFAULT_LANG):
""" """
Busca una serie a través de una serie de parámetros. Search for a series through a series of parameters.
@param name: nombre a buscar @param name: name to search
@type name: str @type name: str
@param imdb_id: codigo identificativo de imdb @param imdb_id: imdb identification code
@type imdb_id: str @type imdb_id: str
@param zap2it_id: codigo identificativo de zap2it @param zap2it_id: zap2it identification code
@type zap2it_id: str @type zap2it_id: str
@param lang: código de idioma @param lang: language code
@type lang: str @type lang: str
data:{ data:{
@@ -756,10 +747,10 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
# if isinstance(ex, urllib.parse).HTTPError: # 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)) 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: else:
dict_html = jsontools.load(html) dict_html = jsontools.load(html)
@@ -777,16 +768,16 @@ class Tvdb(object):
else: else:
index = 0 index = 0
logger.debug("resultado %s" % resultado) logger.debug("result %s" % resultado)
self.list_results = resultado self.list_results = resultado
self.result = resultado[index] self.result = resultado[index]
def __get_by_id(self, _id, lang=DEFAULT_LANG, from_get_list=False): def __get_by_id(self, _id, lang=DEFAULT_LANG, from_get_list=False):
""" """
Obtiene los datos de una serie por identificador. Gets the data for a string by identifier.
@param _id: código de la serie @param _id: series code
@type _id: str @type _id: str
@param lang: código de idioma @param lang: language code
@type lang: str @type lang: str
@rtype: dict @rtype: dict
@return: @return:
@@ -845,10 +836,10 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
# if isinstance(ex, urllib).HTTPError: # 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)) 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: else:
dict_html = jsontools.load(html) dict_html = jsontools.load(html)
@@ -860,7 +851,7 @@ class Tvdb(object):
if not resultado1 and from_get_list: if not resultado1 and from_get_list:
return self.__get_by_id(_id, "en") 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}]} resultado2 = {"image_poster": [{'keyType': 'poster', 'fileName': 'posters/%s-1.jpg' % _id}]}
resultado3 = {"image_fanart": [{'keyType': 'fanart', 'fileName': 'fanart/original/%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(resultado2)
resultado.update(resultado3) resultado.update(resultado3)
logger.debug("resultado total %s" % resultado) logger.debug("total result %s" % resultado)
self.list_results = [resultado] self.list_results = [resultado]
self.result = resultado self.result = resultado
@@ -876,15 +867,15 @@ class Tvdb(object):
def get_images(self, _id, image="poster", season=1, lang="en"): def get_images(self, _id, image="poster", season=1, lang="en"):
""" """
Obtiene un tipo de imagen para una serie para un idioma. Gets an image type for a string for a language.
@param _id: identificador de la serie @param _id: series identifier
@type _id: str @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 image: str
@type season: numero de temporada @type season: season number
@param lang: código de idioma para el que se busca @param lang: language code for which you are searching
@type lang: str @type lang: str
@return: diccionario con el tipo de imagenes elegidas. @return: dictionary with the type of images chosen.
@rtype: dict @rtype: dict
""" """
@@ -918,7 +909,7 @@ class Tvdb(object):
except Exception as ex: except Exception as ex:
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) 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 {} return {}
@@ -932,12 +923,12 @@ class Tvdb(object):
def get_tvshow_cast(self, _id, lang=DEFAULT_LANG): def get_tvshow_cast(self, _id, lang=DEFAULT_LANG):
""" """
obtiene el casting de una serie gets casting for a series
@param _id: codigo de la serie @param _id: series code
@type _id: str @type _id: str
@param lang: codigo idioma para buscar @param lang: language code to search
@type lang: str @type lang: str
@return: diccionario con los actores @return: dictionary with actors
@rtype: dict @rtype: dict
""" """
logger.info() logger.info()
@@ -958,23 +949,22 @@ class Tvdb(object):
def get_id(self): def get_id(self):
""" """
@return: Devuelve el identificador Tvdb de la serie cargada o una cadena vacia en caso de que no @return: Returns the Tvdb identifier of the loaded string or an empty string in case nothing was loaded.
hubiese nada cargado. Se puede utilizar este metodo para saber si una busqueda ha dado resultado o no. You can use this method to find out if a search has been successful or not.
@rtype: str @rtype: str
""" """
return str(self.result.get('id', "")) return str(self.result.get('id', ""))
def get_list_results(self): def get_list_results(self):
""" """
Devuelve los resultados encontramos para una serie. Returns the results we found for a series.
@rtype: list @rtype: list
@return: lista de resultados @return: list of results
""" """
logger.info() logger.info()
list_results = [] list_results = []
# TODO revisar condicion # if we have a result and it has seriesName, we already have the info of the series, it is not necessary to search again
# si tenemos un resultado y tiene seriesName, ya tenemos la info de la serie, no hace falta volver a buscar
if len(self.list_results) == 1 and "seriesName" in self.result: if len(self.list_results) == 1 and "seriesName" in self.result:
list_results.append(self.result) list_results.append(self.result)
info_load = True info_load = True
@@ -1005,16 +995,15 @@ class Tvdb(object):
def get_infoLabels(self, infoLabels=None, origen=None): 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 @type infoLabels: dict
@param origen: Diccionario origen de donde se obtiene los infoLabels, por omision self.result @param origen: Diccionario origen de donde se obtiene los infoLabels, por omision self.result
@type origen: dict @type origen: dict
@return: Devuelve la informacion extra obtenida del objeto actual. Si se paso el parametro infoLables, el valor @return: Returns the extra information obtained from the current object. If the infoLables parameter was passed,
devuelto sera el leido como parametro debidamente actualizado. the value returned will be read as a parameter duly updated.
@rtype: dict @rtype: dict
""" """
# TODO revisar
if infoLabels: if infoLabels:
# logger.debug("es instancia de infoLabels") # logger.debug("es instancia de infoLabels")
ret_infoLabels = InfoLabels(infoLabels) ret_infoLabels = InfoLabels(infoLabels)
@@ -1024,7 +1013,7 @@ class Tvdb(object):
# fix # fix
ret_infoLabels['mediatype'] = 'tvshow' ret_infoLabels['mediatype'] = 'tvshow'
# Iniciar listados # Start Listings
l_castandrole = ret_infoLabels.get('castandrole', []) l_castandrole = ret_infoLabels.get('castandrole', [])
# logger.debug("self.result %s" % self.result) # logger.debug("self.result %s" % self.result)
@@ -1067,9 +1056,9 @@ class Tvdb(object):
elif k == 'status': elif k == 'status':
# se traduce los estados de una serie # 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': elif k == 'network':
ret_infoLabels['studio'] = v ret_infoLabels['studio'] = v
@@ -1094,8 +1083,8 @@ class Tvdb(object):
# ret_infoLabels['code'] = v # ret_infoLabels['code'] = v
elif k in "rating": elif k in "rating":
# traducimos la clasificación por edades (content rating system) # we translate the age rating (content rating system)
ret_infoLabels['mpaa'] = DICT_MPAA.get(v, v) ret_infoLabels['mpaa'] = v
elif k in "genre": elif k in "genre":
genre_list = "" genre_list = ""
@@ -1104,7 +1093,7 @@ class Tvdb(object):
genre_list += ", " genre_list += ", "
# traducimos los generos # traducimos los generos
genre_list += DICT_GENRE.get(i, i) genre_list += i
ret_infoLabels['genre'] = genre_list 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())]) l_castandrole.extend([(p['name'], p['role']) for p in v if p['name'] not in list(dic_aux.keys())])
else: else:
logger.debug("Atributos no añadidos: %s=%s" % (k, v)) logger.debug("Attributes not added: %s=%s" % (k, v))
pass pass
# Ordenar las listas y convertirlas en str si es necesario # Sort the lists and convert them to str if necessary
if l_castandrole: if l_castandrole:
ret_infoLabels['castandrole'] = l_castandrole ret_infoLabels['castandrole'] = l_castandrole
+2 -9
View File
@@ -66,15 +66,8 @@ class Cursor(object):
def prepare_decoder(self,offset): def prepare_decoder(self,offset):
initial_value = self.initial_value + int(offset/16) initial_value = self.initial_value + int(offset/16)
try: from lib import pyaes
from Cryptodome.Cipher import AES self.decryptor = pyaes.AESModeOfOperationCTR(self._file._client.a32_to_str(self.k), counter=pyaes.Counter(initial_value=initial_value))
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))
rest = offset - int(offset/16)*16 rest = offset - int(offset/16)*16
if rest: if rest:
self.decode(str(0)*rest) self.decode(str(0)*rest)
+1 -1
View File
@@ -581,7 +581,7 @@ def set_infolabels(listitem, item, player=False):
listitem.setInfo("video", infoLabels_kodi) listitem.setInfo("video", infoLabels_kodi)
except: except:
listitem.setInfo("video", item.infoLabels) listitem.setInfo("video", item.infoLabels)
logger.error(item.infoLabels) # logger.error(item.infoLabels)
# if item.infoLabels: # if item.infoLabels:
# if 'mediatype' not in item.infoLabels: # if 'mediatype' not in item.infoLabels:
+9 -7
View File
@@ -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 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" changelog += commitJson['commit']['message'] + "\n"
poFilesChanged = True poFilesChanged = True
serviceChanged = True
break break
for file in commitJson['files']: for file in commitJson['files']:
@@ -172,13 +173,6 @@ def check(background=False):
localCommitFile = open( localCommitFile = open(
os.path.join(xbmc.translatePath("special://home/addons/"), 'plugin.video.kod', trackingFile), os.path.join(xbmc.translatePath("special://home/addons/"), 'plugin.video.kod', trackingFile),
'w') # il file di tracking viene eliminato, lo ricreo '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.seek(0)
localCommitFile.truncate() localCommitFile.truncate()
@@ -188,6 +182,14 @@ def check(background=False):
if poFilesChanged: if poFilesChanged:
refreshLang() refreshLang()
updated = True 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: else:
logger.info('Nessun nuovo aggiornamento') logger.info('Nessun nuovo aggiornamento')
+7 -2
View File
@@ -80,7 +80,7 @@ def mark_auto_as_watched(item):
videolibrary.mark_content_as_watched2(item) videolibrary.mark_content_as_watched2(item)
break break
time.sleep(30) time.sleep(5)
# Sincronizacion silenciosa con Trakt # Sincronizacion silenciosa con Trakt
if sync_with_trakt and config.get_setting("trakt_sync"): 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)): 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' 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') title_plain = title_plain.decode('utf-8')
item.library_playcounts.update({title_plain: playCount_final}) #actualizamos el playCount del .nfo 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) sql = 'UPDATE path SET strPath="%s" WHERE idPath=%s' % (strPath, idPath)
logger.info('sql: ' + sql) logger.info('sql: ' + sql)
nun_records, records = execute_sql_kodi(sql) nun_records, records = execute_sql_kodi(sql)
else:
progress.update(100)
xbmc.sleep(1000)
progress.close()
return
p = 80 p = 80
progress.update(p, config.get_localized_string(20000), config.get_localized_string(80013)) progress.update(p, config.get_localized_string(20000), config.get_localized_string(80013))
+9 -1
View File
@@ -2504,6 +2504,10 @@ msgctxt "#60598"
msgid "Video library configuration" msgid "Video library configuration"
msgstr "" msgstr ""
msgctxt "#60599"
msgid "Video library update configuration"
msgstr ""
msgctxt "#60600" msgctxt "#60600"
msgid "TV shows" msgid "TV shows"
msgstr "" msgstr ""
@@ -5181,7 +5185,7 @@ msgid "Remove"
msgstr "" msgstr ""
msgctxt "#70600" msgctxt "#70600"
msgid "Add Season" msgid "Add season"
msgstr "" msgstr ""
msgctxt "#70601" msgctxt "#70601"
@@ -6011,6 +6015,10 @@ msgctxt "#70806"
msgid "Changing this parameter permanently overwrites the Elementum settings.\nDo you want to continue?" msgid "Changing this parameter permanently overwrites the Elementum settings.\nDo you want to continue?"
msgstr "" 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 ] # DNS start [ settings and declaration ]
msgctxt "#707401" msgctxt "#707401"
msgid "Enable DNS check alert" msgid "Enable DNS check alert"
+11 -3
View File
@@ -2503,6 +2503,10 @@ msgctxt "#60598"
msgid "Video library configuration" msgid "Video library configuration"
msgstr "Configurazione videoteca" msgstr "Configurazione videoteca"
msgctxt "#60599"
msgid "Video library update configuration"
msgstr "Configurazione aggiornamento videoteca"
msgctxt "#60600" msgctxt "#60600"
msgid "TV shows" msgid "TV shows"
msgstr "Serie TV" msgstr "Serie TV"
@@ -3389,7 +3393,7 @@ msgstr "Server"
msgctxt "#70146" msgctxt "#70146"
msgid "Add to video library" msgid "Add to video library"
msgstr "Aggiungi alla Videoteca" msgstr "Aggiungi alla videoteca"
msgctxt "#70147" msgctxt "#70147"
msgid "Video library (update TV show)" msgid "Video library (update TV show)"
@@ -5180,8 +5184,8 @@ msgid "Remove"
msgstr "Rimuovi" msgstr "Rimuovi"
msgctxt "#70600" msgctxt "#70600"
msgid "Add Season" msgid "Add season"
msgstr "Aggiungi Stagione" msgstr "Aggiungi stagione"
msgctxt "#70601" msgctxt "#70601"
msgid "Update from the Internet:" 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?" 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?" 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 ] # DNS start [ settings and declaration ]
msgctxt "#707401" msgctxt "#707401"
msgid "Enable DNS check alert" msgid "Enable DNS check alert"
@@ -57,6 +57,7 @@
<width>349</width> <width>349</width>
<height>500</height> <height>500</height>
<texture></texture> <texture></texture>
<aspectratio>keep</aspectratio>
<animation type="WindowOpen" reversible="false"> <animation type="WindowOpen" reversible="false">
<effect type="slide" start="200,0" end="0,0" delay="300" tween="cubic" time="200" /> <effect type="slide" start="200,0" end="0,0" delay="300" tween="cubic" time="200" />
<effect type="fade" delay="300" end="100" time="240" /> <effect type="fade" delay="300" end="100" time="240" />
+42
View File
@@ -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": ""
}
+48
View File
@@ -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
+11 -6
View File
@@ -73,13 +73,18 @@ def elementum_download(item):
if elementum_setting: if elementum_setting:
set_elementum(True) set_elementum(True)
time.sleep(3) time.sleep(3)
TorrentName = match(item.url, patron=r'btih(?::|%3A)([^&%]+)', string=True).match if config.get_setting('downloadpath').startswith('smb'):
post = 'uri=%s&file=null&all=1' % urllib.quote_plus(item.url) select = platformtools.dialog_yesno('Elementum', config.get_localized_string(70807))
match(elementum_host + 'add', post=post, timeout=5, alfa_s=True, ignore_response_code=True) if select:
while not filetools.isfile(filetools.join(elementum_setting.getSetting('torrents_path'), TorrentName + '.torrent')): xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?eyJjaGFubmVsIjoic2hvcnRjdXRzIiwgImFjdGlvbiI6IlNldHRpbmdPblBvc2l0aW9uIiwgImNhdGVnb3J5Ijo2LCAic2V0dGluZyI6MX0=)")
time.sleep(1) 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(): def elementum_monitor():
+4
View File
@@ -256,6 +256,10 @@ def check_for_update(overwrite=True):
item_dummy = Item() item_dummy = Item()
videolibrary.list_movies(item_dummy, silent=True) videolibrary.list_movies(item_dummy, silent=True)
if config.get_setting('trakt_sync'):
from core import trakt_tools
trakt_tools.update_all()
def viewmodeMonitor(): def viewmodeMonitor():
try: try:
+22 -24
View File
@@ -1,9 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import xbmc, xbmcgui, os import xbmc, xbmcgui
from platformcode import config, platformtools, logger from platformcode import config, platformtools
from time import time, sleep from time import time, sleep
from core import scrapertools
from core import jsontools, filetools from core import jsontools, filetools
from core.support import log
from core.item import Item
from platformcode.launcher import play_from_library
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
from concurrent import futures from concurrent import futures
@@ -24,19 +27,18 @@ def check(item):
def return_item(item): def return_item(item):
logger.info() log()
with futures.ThreadPoolExecutor() as executor: with futures.ThreadPoolExecutor() as executor:
future = executor.submit(next_ep, item) future = executor.submit(next_ep, item)
item = future.result() item = future.result()
return item return item
def run(item): def run(item):
logger.info() log()
with futures.ThreadPoolExecutor() as executor: with futures.ThreadPoolExecutor() as executor:
future = executor.submit(next_ep, item) future = executor.submit(next_ep, item)
item = future.result() item = future.result()
if item.next_ep: if item.next_ep:
from platformcode.launcher import play_from_library
return play_from_library(item) return play_from_library(item)
@@ -47,7 +49,7 @@ def videolibrary(item):
def next_ep(item): def next_ep(item):
logger.info() log()
condition = config.get_setting('next_ep') condition = config.get_setting('next_ep')
item.next_ep = False item.next_ep = False
item.show_server = True item.show_server = True
@@ -56,16 +58,14 @@ def next_ep(item):
time_over = False time_over = False
time_limit = time() + 30 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') 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 # wait until the video plays
while not platformtools.is_playing() and time() < time_limit: while not platformtools.is_playing() and time() < time_limit:
sleep(1) sleep(1)
while platformtools.is_playing() and time_over == False: while platformtools.is_playing() and not time_over:
try: try:
Total = xbmc.Player().getTotalTime() Total = xbmc.Player().getTotalTime()
Actual = xbmc.Player().getTime() Actual = xbmc.Player().getTime()
@@ -78,11 +78,11 @@ def next_ep(item):
if time_over: if time_over:
if condition == 1: # hide server afther x second if condition == 1: # hide server afther x second
item.show_server = False item.show_server = False
elif condition == 2: # play next fileif exist elif condition == 2: # play next file if exist
# check i next file exist # check if next file exist
current_filename = os.path.basename(item.strm_path) current_filename = filetools.basename(item.strm_path)
base_path = os.path.basename(os.path.normpath(os.path.dirname(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) path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"),base_path)
fileList = [] fileList = []
for file in filetools.listdir(path): for file in filetools.listdir(path):
@@ -96,11 +96,10 @@ def next_ep(item):
next_file = None next_file = None
else: else:
next_file = fileList[nextIndex] next_file = fileList[nextIndex]
logger.info('NEXTFILE' + next_file) log('Next File:', next_file)
# start next episode window afther x time # start next episode window afther x time
if next_file: if next_file:
from core.item import Item
season_ep = next_file.split('.')[0] season_ep = next_file.split('.')[0]
season = season_ep.split('x')[0] season = season_ep.split('x')[0]
episode = season_ep.split('x')[1] episode = season_ep.split('x')[1]
@@ -111,13 +110,13 @@ def next_ep(item):
contentEpisodeNumber= episode, contentEpisodeNumber= episode,
contentSeason= season, contentSeason= season,
contentTitle= next_ep, contentTitle= next_ep,
contentType= 'tvshow', contentType= 'episode',
infoLabels= {'episode': episode, 'mediatype': 'tvshow', 'season': season, 'title': next_ep}, infoLabels= {'episode': episode, 'mediatype': 'episode', 'season': season, 'title': next_ep},
strm_path= filetools.join(base_path, next_file)) strm_path= filetools.join(base_path, next_file))
global INFO global INFO
INFO = filetools.join(path, next_file.replace("strm", "nfo")) 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 = NextDialog(ND, config.get_runtime_path())
nextDialog.show() nextDialog.show()
@@ -126,7 +125,7 @@ def next_ep(item):
pass pass
nextDialog.close() nextDialog.close()
logger.info('Next Episode: ' +str(nextDialog.stillwatching)) log('Next Episode:', nextDialog.stillwatching)
if nextDialog.stillwatching or nextDialog.continuewatching: if nextDialog.stillwatching or nextDialog.continuewatching:
item.next_ep = True item.next_ep = True
@@ -135,7 +134,6 @@ def next_ep(item):
sleep(1) sleep(1)
xbmc.executebuiltin('Action(Back)') xbmc.executebuiltin('Action(Back)')
sleep(0.5) sleep(0.5)
from platformcode.launcher import play_from_library
return play_from_library(item) return play_from_library(item)
else: else:
item.show_server = False item.show_server = False
@@ -155,7 +153,7 @@ class NextDialog(xbmcgui.WindowXMLDialog):
continuewatching = True continuewatching = True
def __init__(self, *args, **kwargs): 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.action_exitkeys_id = [xbmcgui.ACTION_STOP, xbmcgui.ACTION_BACKSPACE, xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK]
self.progress_control = None self.progress_control = None
@@ -203,7 +201,7 @@ class NextDialog(xbmcgui.WindowXMLDialog):
self.close() self.close()
def onAction(self, action): def onAction(self, action):
logger.info() log()
if action in self.action_exitkeys_id: if action in self.action_exitkeys_id:
self.set_continue_watching(False) self.set_continue_watching(False)
self.close() self.close()
+42 -4
View File
@@ -181,6 +181,7 @@ def list_tvshows(item):
itemlist = [] itemlist = []
dead_list = [] dead_list = []
zombie_list = [] zombie_list = []
lista = []
# Obtenemos todos los tvshow.nfo de la videoteca de SERIES recursivamente # Obtenemos todos los tvshow.nfo de la videoteca de SERIES recursivamente
for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.TVSHOWS_PATH): for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.TVSHOWS_PATH):
for s in subcarpetas: for s in subcarpetas:
@@ -280,6 +281,7 @@ def list_tvshows(item):
else: else:
texto_update = config.get_localized_string(60023) texto_update = config.get_localized_string(60023)
value = 1 value = 1
item_tvshow.title += " [B]" + u"\u2022".encode('utf-8') + "[/B]"
# item_tvshow.text_color = "0xFFDF7401" # item_tvshow.text_color = "0xFFDF7401"
# Menu contextual: Eliminar serie/canal # Menu contextual: Eliminar serie/canal
@@ -323,8 +325,7 @@ def list_tvshows(item):
## verifica la existencia de los canales ## ## verifica la existencia de los canales ##
if len(item_tvshow.library_urls) > 0: if len(item_tvshow.library_urls) > 0:
itemlist.append(item_tvshow) 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: if itemlist:
itemlist = sorted(itemlist, key=lambda it: it.title.lower()) 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, itemlist.append(Item(channel=item.channel, action="update_videolibrary", thumbnail=item.thumbnail,
title=typo(config.get_localized_string(70269), 'bold color kod'), folder=False)) 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 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): def get_seasons(item):
logger.info() logger.info()
@@ -1076,13 +1113,14 @@ def mark_season_as_watched(item):
platformtools.itemlist_refresh() platformtools.itemlist_refresh()
def mark_tvshow_as_updatable(item): def mark_tvshow_as_updatable(item, silent=False):
logger.info() logger.info()
head_nfo, it = videolibrarytools.read_nfo(item.nfo) head_nfo, it = videolibrarytools.read_nfo(item.nfo)
it.active = item.active it.active = item.active
filetools.write(item.nfo, head_nfo + it.tojson()) filetools.write(item.nfo, head_nfo + it.tojson())
platformtools.itemlist_refresh() if not silent:
platformtools.itemlist_refresh()
def delete(item): def delete(item):