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

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>
<!-- <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 &quot;di kod&quot; 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 è &quot;più rapido&quot;, 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>

View File

@@ -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"
}

View File

@@ -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)

View File

@@ -1,7 +1,7 @@
{
"id": "animesubita",
"name": "AnimeSubIta",
"active": true,
"active": false,
"language": ["sub-ita"],
"thumbnail": "animesubita.png",
"bannermenu": "animesubita.png",

View File

@@ -1,7 +1,7 @@
{
"id": "animetubeita",
"name": "AnimeTubeITA",
"active": true,
"active": false,
"language": ["sub-ita"],
"thumbnail": "animetubeita.png",
"bannermenu": "animetubeita.png",

View File

@@ -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))

View File

@@ -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)

View File

@@ -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,

View File

@@ -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 &raquo;</a>'
patronNext=r'a class="next page-numbers" href="?([^>"]+)">Avanti &raquo;</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)

View File

@@ -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)

View File

@@ -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):

View File

@@ -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'}

View File

@@ -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):

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
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)

View File

@@ -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 ''

View File

@@ -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
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -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':

View File

@@ -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'))

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

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
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')

View File

@@ -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))

View File

@@ -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"

View File

@@ -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"

View File

@@ -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
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
servers/hdmario.py Normal file
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

View File

@@ -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():

View File

@@ -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:

View File

@@ -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()

View File

@@ -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):