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