From 114fed7f31a26219e42eb887277752e9daba1c08 Mon Sep 17 00:00:00 2001 From: mac12m99 <10120390+mac12m99@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:40:17 +0200 Subject: [PATCH] KoD 1.7 - Aggiunto menu globale opzioni di KoD\n- Aggiunto canale tapmovie e server annessi\n- Notifica quando il tipo di vista viene salvata (con indicazione del tipo di contenuto)\n\n --- addon.xml | 18 +- channels.json | 8 +- channels/animeworld.py | 1 + channels/dreamsub.py | 8 +- channels/guardaseriecam.json | 2 +- channels/ilgeniodellostreaming_cam.json | 2 +- channels/tapmovie.json | 11 + channels/tapmovie.py | 102 +++ contextmenu.py | 63 ++ core/resolverdns.py | 2 +- core/support.py | 57 +- core/tmdb.py | 747 ++++++++++-------- core/videolibrarytools.py | 61 +- externalsearch.py | 80 -- platformcode/autorenumber.py | 2 + platformcode/contextmenu/contextmenu.json | 5 + platformcode/contextmenu/search.py | 127 +++ platformcode/contextmenu/trailer.py | 23 + platformcode/contextmenu/tvshow_options.py | 214 +++++ platformcode/infoplus.py | 8 +- platformcode/launcher.py | 2 +- platformcode/platformtools.py | 361 +++++++-- platformcode/shortcuts.py | 2 +- platformcode/xbmc_videolibrary.py | 21 +- .../resource.language.en_gb/strings.po | 22 +- .../resource.language.it_it/strings.po | 27 +- resources/settings.xml | 4 +- servers/fembed.py | 17 +- servers/hxfile.json | 42 + servers/hxfile.py | 25 + servers/mixdrop.json | 4 + servers/playtube.json | 43 + servers/playtube.py | 29 + servers/speedvideo.py | 5 +- servers/vidmoly.json | 2 +- servers/youdbox.json | 7 +- service.py | 35 +- specials/globalsearch.py | 2 +- specials/search.py | 11 +- specials/trailertools.py | 7 +- specials/tvmoviedb.json | 4 +- specials/tvmoviedb.py | 122 +-- updatetvshow.py | 118 --- 43 files changed, 1632 insertions(+), 821 deletions(-) create mode 100644 channels/tapmovie.json create mode 100644 channels/tapmovie.py create mode 100644 contextmenu.py delete mode 100644 externalsearch.py create mode 100644 platformcode/contextmenu/contextmenu.json create mode 100644 platformcode/contextmenu/search.py create mode 100644 platformcode/contextmenu/trailer.py create mode 100644 platformcode/contextmenu/tvshow_options.py create mode 100644 servers/hxfile.json create mode 100644 servers/hxfile.py create mode 100644 servers/playtube.json create mode 100644 servers/playtube.py delete mode 100644 updatetvshow.py diff --git a/addon.xml b/addon.xml index fe15bba8..78137397 100644 --- a/addon.xml +++ b/addon.xml @@ -1,4 +1,4 @@ - + @@ -11,14 +11,10 @@ - - - String.IsEqual(ListItem.dbtype,tvshow) + + + !String.StartsWith(ListItem.FileNameAndPath, plugin://plugin.video.kod/) + [ String.IsEqual(ListItem.dbtype, tvshow) | String.IsEqual(ListItem.dbtype, movie) | String.IsEqual(ListItem.dbtype, season) | String.IsEqual(ListItem.dbtype, episode) ] - - - - @@ -31,8 +27,10 @@ resources/media/screenshot-2.png resources/media/screenshot-3.png - - Corretto blocco nella ricerca globale - - migliorie e fix vari ai canali e al core + - Aggiunto menu globale "opzioni di KoD" +- Aggiunto canale tapmovie e server annessi +- Notifica quando il tipo di vista viene salvata (con indicazione del tipo di contenuto) + Naviga velocemente sul web e guarda i contenuti presenti [COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR] [COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR] diff --git a/channels.json b/channels.json index c19d4056..af78f550 100644 --- a/channels.json +++ b/channels.json @@ -1,7 +1,7 @@ { "direct": { "altadefinizione01": "https://www.altadefinizione01.games", - "altadefinizione01_link": "https://altadefinizione01.cheap", + "altadefinizione01_link": "https://altadefinizione01.travel", "animealtadefinizione": "https://www.animealtadefinizione.it", "animeforce": "https://www.animeforce.it", "animeleggendari": "https://animezeus.com", @@ -12,7 +12,7 @@ "casacinema": "https://www.casacinema.page", "cb01anime": "https://www.cineblog01.red", "cineblog01": "https://cb01.uno", - "cinemalibero": "https://cinemalibero.monster", + "cinemalibero": "https://cinemalibero.blog", "cinetecadibologna": "http://cinestore.cinetecadibologna.it", "discoveryplus": "https://www.discoveryplus.com", "dreamsub": "https://dreamsub.stream", @@ -26,11 +26,11 @@ "ilcorsaronero": "https://ilcorsaronero.link", "ilgeniodellostreaming": "https://ilgeniodellostreaming.ist", "ilgeniodellostreaming_cam": "https://ilgeniodellostreaming.shop", - "italiaserie": "https://italiaserie.work", + "italiaserie": "https://italiaserie.cam", "mediasetplay": "https://www.mediasetplay.mediaset.it", "mondoserietv": "https://mondoserietv.club", "paramount": "https://www.paramountnetwork.it", - "piratestreaming": "https://www.piratestreaming.bar", + "piratestreaming": "https://www.piratestreaming.shop", "polpotv": "https://roma.polpo.tv", "raiplay": "https://www.raiplay.it", "serietvonline": "https://serietvonline.art", diff --git a/channels/animeworld.py b/channels/animeworld.py index 7c91037c..f443070c 100644 --- a/channels/animeworld.py +++ b/channels/animeworld.py @@ -20,6 +20,7 @@ def get_cookie(data): def get_data(item): + # support.dbg() url = httptools.downloadpage(item.url, headers=headers, follow_redirects=True, only_headers=True).url data = support.match(url, headers=headers, follow_redirects=True).data if 'AWCookieVerify' in data: diff --git a/channels/dreamsub.py b/channels/dreamsub.py index 815993d5..d4a9ca75 100644 --- a/channels/dreamsub.py +++ b/channels/dreamsub.py @@ -29,6 +29,7 @@ def mainlist(item): def menu(item): item.contentType = '' action = 'peliculas' + patronBlock = r'
%s(?P.*?)
' % item.args patronMenu = r'[^>]+)>[^>]+>[^>]+>[^>]+>(?P[^>]+)</a>' @@ -89,7 +90,7 @@ def peliculas(item): patronBlock = r'<div id="%s"[^>]+>(?P<block>.*?)<div class="vistaDettagliata"' % item.args[1] patron = r'<li>\s*<a href="(?P<url>[^"]+)" title="(?P<title>[^"]+)" class="thumb">[^>]+>[^>]+>[^>]+>\s*[EePp]+\s*(?P<episode>\d+)[^>]+>\s<img src="(?P<thumb>[^"]+)"' else: - patron = r'<div class="showStreaming"> +<b>(?P<title>[^<]+)[^>]+>[^>]+>\s*<span>Lingua:\s*(?P<lang>[^>]+)?>[<>br\s]+a href="(?P<url>[^"]+)"[^>]+>.*?--image-url:url\(/*(?P<thumb>[^\)]+).*?Anno di inizio</b>:\s*(?P<year>[0-9]{4})' + patron = r'<div class="showStreaming">\s*<b>(?P<title>[^<]+)[^>]+>[^>]+>\s*<span>Lingua:\s*(?:DUB|JAP)?\s*(?P<lang>(?:SUB )?ITA)[^>]+>[<>br\s]+a href="(?P<url>[^"]+)"[^>]+>.*?--image-url:url\(/*(?P<thumb>[^\)]+).*?Anno di inizio</b>:\s*(?P<year>[0-9]{4})' patronNext = '<li class="currentPage">[^>]+><li[^<]+<a href="([^"]+)">' def itemHook(item): @@ -128,7 +129,6 @@ def findvideos(item): if 'vvvvid' in matches.data: itemlist.append(item.clone(action="play", title='VVVVID', url=support.match(matches.data, patron=r'(http://www.vvvvid[^"]+)').match, server='vvvvid')) else: - # matches.matches.sort() support.info('VIDEO') for url in matches.matches: lang = url.split('/')[-2] @@ -139,8 +139,6 @@ def findvideos(item): quality = url.split('/')[-1].split('?')[0] url += '|User-Agent=' + support.httptools.get_user_agent() + '&Referer=' + url - itemlist.append(item.clone(action="play", title=language, url=url, contentLanguage = language, quality = quality, order = quality.replace('p','').zfill(4), server='directo',)) - - itemlist.sort(key=lambda x: (x.title, x.order), reverse=False) + itemlist.append(item.clone(action="play", title='', url=url, contentLanguage = language, quality = quality, order = quality.replace('p','').zfill(4), server='directo',)) return support.server(item, itemlist=itemlist) diff --git a/channels/guardaseriecam.json b/channels/guardaseriecam.json index f0e78dfd..ccd7af1a 100644 --- a/channels/guardaseriecam.json +++ b/channels/guardaseriecam.json @@ -2,7 +2,7 @@ "id": "guardaseriecam", "name": "GuardaSerie Cam", "language": ["ita", "sub-ita"], - "active": true, + "active": false, "thumbnail": "https://raw.githubusercontent.com/32Dexter/DexterRepo/master/media/guardaserie_live.png", "banner": "", "categories": ["tvshow"], diff --git a/channels/ilgeniodellostreaming_cam.json b/channels/ilgeniodellostreaming_cam.json index f51f9627..78746f9b 100644 --- a/channels/ilgeniodellostreaming_cam.json +++ b/channels/ilgeniodellostreaming_cam.json @@ -1,7 +1,7 @@ { "id": "ilgeniodellostreaming_cam", "name": "IlGenioDelloStreaming CAM", - "active": true, + "active": false, "language": ["ita"], "thumbnail": "ilgeniodellostreaming.png", "banner": "ilgeniodellostreaming.png", diff --git a/channels/tapmovie.json b/channels/tapmovie.json new file mode 100644 index 00000000..6087cea8 --- /dev/null +++ b/channels/tapmovie.json @@ -0,0 +1,11 @@ +{ + "id": "tapmovie", + "name": "Tap Movie", + "language": ["ita", "sub-ita"], + "active": true, + "thumbnail": "tapmovie.png", + "banner": "tapmovie.png", + "categories": ["movie", "tvshow", "anime"], + "not_active": ["include_in_newest"], + "settings": [] +} diff --git a/channels/tapmovie.py b/channels/tapmovie.py new file mode 100644 index 00000000..76459651 --- /dev/null +++ b/channels/tapmovie.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------ +# Canale per 'dvdita' + +from core import support, httptools +from core.item import Item +import sys +if sys.version_info[0] >= 3: from concurrent import futures +else: from concurrent_py2 import futures + +host = support.config.get_channel_url() +api_url = '/api/v2/' +per_page = 24 + + +@support.menu +def mainlist(item): + film = ['/browse/movie'] + tvshow = ['/browse/tvshow'] + search = '' + + # [Voce Menu,['url','action','args',contentType] + top = [('Generi', ['', 'genres', '', 'undefined'])] + + return locals() + + +def episodios(item): + support.info(item) + itemlist = [] + + with futures.ThreadPoolExecutor() as executor: + thL = [] + for season in httptools.downloadpage(host + api_url + 'tvshow', post={'tvshow_id': item.id}).json.get('season', []): + season_id = season['season_number'] + thL.append(executor.submit(httptools.downloadpage, host + api_url + 'episodes', post={'tvshow_id': item.id, 'season_id': season_id})) + for th in futures.as_completed(thL): + for episode in th.result().json.get('episodes', []): + itemlist.append(item.clone(action="findvideos", contentSeason=episode['season_id'], contentEpisodeNumber=episode['episode_number'], id=item.id, + title=episode['season_id']+'x'+episode['episode_number'], contentType='episode')) + support.scraper.sort_episode_list(itemlist) + support.videolibrary(itemlist, item) + support.download(itemlist, item) + + return itemlist + + +def genres(item): + itemlist = [] + for n, genre in enumerate(httptools.downloadpage(host + api_url + 'categories', post={}).json.get('categories', [])): + itemlist.append(item.clone(action="peliculas", genre=genre.get('name'), title=genre.get('value'), n=n)) + return support.thumb(itemlist, genre=True) + + +def peliculas(item, text=''): + support.info('search', item) + itemlist = [] + filter_type = False + if item.genre: + text = item.genre + cmd = 'search/category' + else: + cmd = 'search' + if not text: + filter_type = True + + try: + page = int(item.url.split('?p=')[1]) + except: + page = 1 + results = httptools.downloadpage(host + api_url + cmd, post={'search': text, 'page': page}).json.get('results', []) + for result in results: + contentType = 'movie' if result['type'] == 'FILM' else 'tvshow' + if not filter_type or (filter_type and contentType == item.contentType): + itemlist.append(item.clone(id=result.get('id'), title=result.get('title'), contentTitle=result.get('title'), + contentSerieName='' if contentType == 'movie' else result.get('title'), + contentPlot=result.get('description'), thumbnail=result.get('poster'), + fanart=result.get('backdrop'), year=result.get('year'), action='episodios' if contentType == 'tvshow' else 'findvideos', + url='{}/{}/{}-{}'.format('https://filmigratis.org', contentType, result.get('id'), support.scrapertools.slugify(result.get('title'))), + contentType=contentType)) + support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) + + if len(results) >= per_page: + page += 1 + support.nextPage(itemlist, item, next_page='https://filmigratis.org/category/' + str(item.n) + '/' + item.genre + '?p=' + str(page)) + return itemlist + + +def search(item, text): + return peliculas(item, text) + + +def findvideos(item): + itemlist = [] + if not item.contentSeason: # film + json = httptools.downloadpage(host + api_url + 'movie', post={'movie_id': item.id}).json + else: + json = httptools.downloadpage(host + api_url + 'episode/links', post={'tvshow_id': item.id, 'season_id': item.contentSeason, 'episode_id': item.contentEpisodeNumber}).json + + for i in json.get('links', []) + json.get('special', []): + itemlist.append(Item(url=i.get('link'))) + return support.server(item, itemlist=itemlist) diff --git a/contextmenu.py b/contextmenu.py new file mode 100644 index 00000000..585c9f98 --- /dev/null +++ b/contextmenu.py @@ -0,0 +1,63 @@ +from platformcode import config, logger +import xbmc, sys, xbmcgui, os + +librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) +sys.path.insert(0, librerias) + +from core import jsontools, support + +addon_id = config.get_addon_core().getAddonInfo('id') + +LOCAL_FILE = os.path.join(config.get_runtime_path(), "platformcode/contextmenu/contextmenu.json") +f = open(LOCAL_FILE) +contextmenu_settings = jsontools.load(open(LOCAL_FILE).read()) +f.close() + + +def build_menu(): + tmdbid = xbmc.getInfoLabel('ListItem.Property(tmdb_id)') + mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') + title = xbmc.getInfoLabel('ListItem.Title') + year = xbmc.getInfoLabel('ListItem.Year') + imdb = xbmc.getInfoLabel('ListItem.IMDBNumber') + filePath = xbmc.getInfoLabel('ListItem.FileNameAndPath') + containerPath = xbmc.getInfoLabel('Container.FolderPath') + + logstr = "Selected ListItem is: 'IMDB: {}' - TMDB: {}' - 'Title: {}' - 'Year: {}'' - 'Type: {}'".format(imdb, tmdbid, title, year, mediatype) + logger.info(logstr) + logger.info(filePath) + logger.info(containerPath) + + contextmenuitems = [] + contextmenuactions = [] + + for itemmodule in contextmenu_settings: + logger.debug('check contextmenu', itemmodule) + module = __import__(itemmodule, None, None, [itemmodule]) + + logger.info('Add contextmenu item ->', itemmodule) + module_item_actions = module.get_menu_items() + contextmenuitems.extend([item for item, fn in module_item_actions]) + contextmenuactions.extend([fn for item, fn in module_item_actions]) + + if len(contextmenuitems) == 0: + logger.info('No contextmodule found, build an empty one') + contextmenuitems.append(empty_item()) + contextmenuactions.append(lambda: None) + + ret = xbmcgui.Dialog().contextmenu(contextmenuitems) + + if ret > -1: + logger.info('Contextmenu module index', ret, ', label=' + contextmenuitems[ret]) + contextmenuactions[ret]() + + +def empty_item(): + return config.get_localized_string(90004) + + +if __name__ == '__main__': + build_menu() + + + diff --git a/core/resolverdns.py b/core/resolverdns.py index 8e87ecd2..325faf35 100644 --- a/core/resolverdns.py +++ b/core/resolverdns.py @@ -114,7 +114,7 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): ret = super(CipherSuiteAdapter, self).send(request, **kwargs) if 400 <= ret.status_code < 500: raise Exception - except Exception as e: + except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError, requests.exceptions.SSLError) as e: logger.info('Request for ' + domain + ' with ip ' + ip + ' failed') logger.info(e) # if 'SSLError' in str(e): diff --git a/core/support.py b/core/support.py index 076569bc..f15760a6 100755 --- a/core/support.py +++ b/core/support.py @@ -152,6 +152,7 @@ def cleantitle(title): cleantitle = '' if title: if type(title) != str: title.decode('UTF-8') + title = scrapertools.unescape(title) title = scrapertools.decodeHtmlentities(title) cleantitle = title.replace('"', "'").replace('×', 'x').replace('–', '-').strip() return cleantitle @@ -386,7 +387,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t contentSerieName= title if 'movie' not in [contentType] and function != 'episodios' else item.contentSerieName, contentTitle= title if 'movie' in [contentType] and function == 'peliculas' else item.contentTitle, contentLanguage = lang1, - contentEpisodeNumber=episode if episode else '', + contentSeason= infolabels.get('season', ''), + contentEpisodeNumber=infolabels.get('episode', ''), news= item.news if item.news else '', other = scraped['other'] if scraped['other'] else '', grouped=group @@ -531,15 +533,25 @@ def scrape(func): itemlist = newFunc() itemlist = [i for i in itemlist if i.action not in ['add_pelicula_to_library', 'add_serie_to_library']] - if action != 'play' and function != 'episodios' and 'patronMenu' not in args and item.contentType in ['movie', 'tvshow', 'episode', 'undefined'] and not disabletmdb: + if anime and inspect.stack()[1][3] not in ['find_episodes']: + from platformcode import autorenumber + if function == 'episodios': autorenumber.start(itemlist, item) + else: autorenumber.start(itemlist) + + if action != 'play' and 'patronMenu' not in args and not disabletmdb and function != 'episodios' and item.contentType in ['movie', 'tvshow', 'episode', 'undefined']: tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) if not group and not args.get('groupExplode') and ((pagination and len(matches) <= pag * pagination) or not pagination): # next page with pagination if patronNext and inspect.stack()[1][3] not in ['newest'] and len(inspect.stack()) > 2 and inspect.stack()[2][3] not in ['get_channel_results']: nextPage(itemlist, item, data, patronNext, function) - # if function == 'episodios': - # scraper.sort_episode_list(itemlist) + for it in itemlist: + if it.contentEpisodeNumber and it.contentSeason: + it.title = '[B]{:d}x{:02d} - {}[/B]'.format(it.contentSeason, it.contentEpisodeNumber, it.infoLabels['title'] if it.infoLabels['title'] else it.fulltitle) + if it.contentLanguage: + it.title += typo(it.contentLanguage, '_ [] color kod') + if it.quality: + it.title += typo(it.quality, '_ [] color kod') # next page for pagination if pagination and len(matches) > pag * pagination and not search: @@ -557,13 +569,7 @@ def scrape(func): thumbnail=thumb(), prevthumb=item.prevthumb if item.prevthumb else item.thumbnail)) - if anime and inspect.stack()[1][3] not in ['find_episodes']: - from platformcode import autorenumber - if function == 'episodios': autorenumber.start(itemlist, item) - else: autorenumber.start(itemlist) - # if anime and autorenumber.check(item) == False and len(itemlist)>0 and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'): - # pass - # else: + if inspect.stack()[1][3] not in ['find_episodes']: if addVideolibrary and (item.infoLabels["title"] or item.fulltitle): # item.fulltitle = item.infoLabels["title"] @@ -1139,7 +1145,10 @@ def nextPage(itemlist, item, data='', patron='', function_or_level=1, next_page= if next_page != "": if resub: next_page = re.sub(resub[0], resub[1], next_page) if 'http' not in next_page: - next_page = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (next_page if next_page.startswith('/') else '/' + next_page) + if '/' in next_page: + next_page = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (next_page if next_page.startswith('/') else '/' + next_page) + else: + next_page = '/'.join(item.url.split('/')[:-1]) + '/' + next_page next_page = next_page.replace('&', '&') logger.debug('NEXT= ', next_page) itemlist.append( @@ -1362,15 +1371,27 @@ def addQualityTag(item, itemlist, data, patron): info('nessun tag qualità trovato') def get_jwplayer_mediaurl(data, srvName, onlyHttp=False, dataIsBlock=False): + from core import jsontools + video_urls = [] - block = scrapertools.find_single_match(data, r'sources:\s*\[([^\]]+)\]') if not dataIsBlock else data + block = scrapertools.find_single_match(data, r'sources:\s*([^\]]+\])') if not dataIsBlock else data if block: - if 'file:' in block: - sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?') - elif 'src:' in block: - sources = scrapertools.find_multiple_matches(block, r'src:\s*"([^"]+)",\s*type:\s*"[^"]+"(?:,[^,]+,\s*label:\s*"([^"]+)")?') + json = jsontools.load(block) + if json: + sources = [] + for s in json: + if 'file' in s.keys(): + src = s['file'] + else: + src = s['src'] + sources.append((src, s.get('label'))) else: - sources =[(block.replace('"',''), '')] + if 'file:' in block: + sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?') + elif 'src:' in block: + sources = scrapertools.find_multiple_matches(block, r'src:\s*"([^"]+)",\s*type:\s*"[^"]+"(?:,[^,]+,\s*label:\s*"([^"]+)")?') + else: + sources =[(block.replace('"',''), '')] for url, quality in sources: quality = 'auto' if not quality else quality if url.split('.')[-1] != 'mpd': diff --git a/core/tmdb.py b/core/tmdb.py index bbe7cf1b..ee2133f3 100644 --- a/core/tmdb.py +++ b/core/tmdb.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -# from future import standard_library -# standard_library.install_aliases() -# from builtins import str import datetime import sys, requests PY3 = False @@ -27,43 +24,45 @@ info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json def_lang = info_language[config.get_setting("info_language", "videolibrary")] lock = threading.Lock() -# ------------------------------------------------- -------------------------------------------------- -------- -# Set of functions related to infoLabels. -# version 1.0: -# Initial version -# -# Include: -# - set_infoLabels (source, seekTmdb, search_language): Gets and sets (item.infoLabels) the extra data of one or several series, chapters or movies. -# - set_infoLabels_item (item, seekTmdb, search_language): Gets and sets (item.infoLabels) the extra data of a series, chapter or movie. -# - set_infoLabels_itemlist (item_list, seekTmdb, search_language): Gets and sets (item.infoLabels) the data extras from a list of series, chapters or movies. -# - infoLabels_tostring (item): Returns a str with the list ordered with the item's infoLabels -# -# Usage: -# - tmdb.set_infoLabels (item, seekTmdb = True) -# -# Get basic data from a movie: -# Before calling the set_infoLabels method the title to search for must be in item.contentTitle and the year in item.infoLabels ['year']. -# -# Obtain basic data from a series: -# Before calling the set_infoLabels method the title to search for must be in item.show or in item.contentSerieName. -# -# Get more data from a movie or series: -# After obtaining the basic data in item.infoLabels ['tmdb'] we will have the code of the series or movie. -# We could also directly set this code, if known, or use the corresponding code of: -# IMDB (in item.infoLabels ['IMDBNumber'] or item.infoLabels ['code'] or item.infoLabels ['imdb_id']), TVDB (only series, in item.infoLabels ['tvdb_id']), -# Freebase (series only, on item.infoLabels ['freebase_mid']), TVRage (series only, on item.infoLabels ['tvrage_id']) -# -# Get data from a season: -# Before calling the set_infoLabels method the series title must be in item.show or in item.contentSerieName, -# the series TMDB code must be in item.infoLabels ['tmdb'] (it can be set automatically by the basic data query) -# and the season number must be in item.infoLabels ['season']. -# -# Get data from an episode: -# Before calling the set_infoLabels method the series title must be in item.show or in item.contentSerieName, -# the TMDB code of the series must be in item.infoLabels ['tmdb'] (it can be set automatically using the basic data query), -# the season number must be in item.infoLabels ['season'] and the episode number must be in item.infoLabels ['episode']. -# ------------------------------------------------- -------------------------------------------------- ----------- +host = 'https://api.themoviedb.org/3' +api = 'a1ab8b8669da03637a4b98fa39c39228' +""" + Set of functions related to infoLabels. + version 1.0: + Initial version + + Include: + - set_infoLabels (source, seekTmdb, search_language): Gets and sets (item.infoLabels) the extra data of one or several series, chapters or movies. + - set_infoLabels_item (item, seekTmdb, search_language): Gets and sets (item.infoLabels) the extra data of a series, chapter or movie. + - set_infoLabels_itemlist (item_list, seekTmdb, search_language): Gets and sets (item.infoLabels) the data extras from a list of series, chapters or movies. + - infoLabels_tostring (item): Returns a str with the list ordered with the item's infoLabels + + Usage: + - tmdb.set_infoLabels (item, seekTmdb = True) + + Get basic data from a movie: + Before calling the set_infoLabels method the title to search for must be in item.contentTitle and the year in item.infoLabels ['year']. + + Obtain basic data from a series: + Before calling the set_infoLabels method the title to search for must be in item.show or in item.contentSerieName. + + Get more data from a movie or series: + After obtaining the basic data in item.infoLabels ['tmdb'] we will have the code of the series or movie. + We could also directly set this code, if known, or use the corresponding code of: + IMDB (in item.infoLabels ['IMDBNumber'] or item.infoLabels ['code'] or item.infoLabels ['imdb_id']), TVDB (only series, in item.infoLabels ['tvdb_id']), + Freebase (series only, on item.infoLabels ['freebase_mid']), TVRage (series only, on item.infoLabels ['tvrage_id']) + + Get data from a season: + Before calling the set_infoLabels method the series title must be in item.show or in item.contentSerieName, + the series TMDB code must be in item.infoLabels ['tmdb'] (it can be set automatically by the basic data query) + and the season number must be in item.infoLabels ['season']. + + Get data from an episode: + Before calling the set_infoLabels method the series title must be in item.show or in item.contentSerieName, + the TMDB code of the series must be in item.infoLabels ['tmdb'] (it can be set automatically using the basic data query), + the season number must be in item.infoLabels ['season'] and the episode number must be in item.infoLabels ['episode']. +""" otmdb_global = None from core import db @@ -155,7 +154,7 @@ def cache_response(fn): return wrapper -def set_infoLabels(source, seekTmdb=True, idioma_busqueda=def_lang, forced=False): +def set_infoLabels(source, seekTmdb=True, search_language=def_lang, forced=False): """ Depending on the data type of source, it obtains and sets (item.infoLabels) the extra data of one or more series, chapters or movies. @@ -163,8 +162,8 @@ def set_infoLabels(source, seekTmdb=True, idioma_busqueda=def_lang, forced=False @type source: list, item @param seekTmdb: if it is True, it searches www.themoviedb.org to obtain the data, otherwise it obtains the data of the Item itself. @type seekTmdb: bool - @param idioma_busqueda: set the language value in case of search at www.themoviedb.org - @type idioma_busqueda: str + @param search_language: set the language value in case of search at www.themoviedb.org + @type search_language: str @return: a number or list of numbers with the result of the calls to set_infoLabels_item @rtype: int, list """ @@ -174,15 +173,15 @@ def set_infoLabels(source, seekTmdb=True, idioma_busqueda=def_lang, forced=False start_time = time.time() if type(source) == list: - ret = set_infoLabels_itemlist(source, seekTmdb, idioma_busqueda) + ret = set_infoLabels_itemlist(source, seekTmdb, search_language) logger.debug("The data of %i links were obtained in %f seconds" % (len(source), time.time() - start_time)) else: - ret = set_infoLabels_item(source, seekTmdb, idioma_busqueda) + ret = set_infoLabels_item(source, seekTmdb, search_language) logger.debug("The data were obtained in %f seconds" % (time.time() - start_time)) return ret -def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang, forced=False): +def set_infoLabels_itemlist(item_list, seekTmdb=False, search_language=def_lang, forced=False): """ Concurrently, it gets the data of the items included in the item_list. @@ -193,8 +192,8 @@ def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang, @type item_list: list @param seekTmdb: If it is True, it searches www.themoviedb.org to obtain the data, otherwise it obtains the data of the Item itself if they exist. @type seekTmdb: bool - @param idioma_busqueda: Language code according to ISO 639-1, in case of search at www.themoviedb.org. - @type idioma_busqueda: str + @param search_language: Language code according to ISO 639-1, in case of search at www.themoviedb.org. + @type search_language: str @return: A list of numbers whose absolute value represents the number of elements included in the infoLabels attribute of each Item. This number will be positive if the data has been obtained from www.themoviedb.org and negative otherwise. @rtype: list @@ -203,33 +202,34 @@ def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang, if not config.get_setting('tmdb_active') and not forced: return # threads_num = config.get_setting("tmdb_threads", default=20) - # semaforo = threading.Semaphore(threads_num) + # semaphore = threading.Semaphore(threads_num) r_list = list() i = 0 - l_hilo = list() + l_thread = list() def sub_thread(_item, _i, _seekTmdb): - # semaforo.acquire() + # semaphore.acquire() ret = 0 try: - ret = set_infoLabels_item(_item, _seekTmdb, idioma_busqueda, lock) + ret = set_infoLabels_item(_item, _seekTmdb, search_language, lock) except: import traceback logger.error(traceback.format_exc(1)) if lock and lock.locked(): lock.release() # logger.debug(str(ret) + "item: " + _item.tostring()) - # semaforo.release() + # semaphore.release() r_list.append((_i, _item, ret)) for item in item_list: - t = threading.Thread(target=sub_thread, args=(item, i, seekTmdb)) - t.start() - i += 1 - l_hilo.append(t) + sub_thread(item, i, seekTmdb) + # t = threading.Thread(target=sub_thread, args=(item, i, seekTmdb)) + # t.start() + # i += 1 + # l_thread.append(t) # wait for all the threads to end - for x in l_hilo: + for x in l_thread: x.join() # Sort results list by call order to keep the same order q item_list @@ -239,7 +239,7 @@ def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang, return [ii[2] for ii in r_list] -def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None): +def set_infoLabels_item(item, seekTmdb=True, search_language=def_lang, lock=None): """ Gets and sets (item.infoLabels) the extra data of a series, chapter or movie. @@ -247,26 +247,28 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None @type item: Item @param seekTmdb: If it is True, it searches www.themoviedb.org to obtain the data, otherwise it obtains the data of the Item itself if they exist. @type seekTmdb: bool - @param idioma_busqueda: Language code according to ISO 639-1, in case of search at www.themoviedb.org. - @type idioma_busqueda: str + @param search_language: Language code according to ISO 639-1, in case of search at www.themoviedb.org. + @type search_language: str @param lock: For use of threads when calling the 'set_infoLabels_itemlist' method @return: A number whose absolute value represents the number of elements included in the item.infoLabels attribute. This number will be positive if the data has been obtained from www.themoviedb.org and negative otherwise. @rtype: int """ global otmdb_global - def __leer_datos(otmdb_aux): - item.infoLabels = otmdb_aux.get_infoLabels(item.infoLabels) - if item.infoLabels['thumbnail']: + def read_data(otmdb_aux): + infoLabels = otmdb_aux.get_infoLabels(item.infoLabels) + if not infoLabels['plot']: infoLabels['plot'] = otmdb_aux.get_plot('en-US') + item.infoLabels = infoLabels + if item.infoLabels.get('thumbnail'): item.thumbnail = item.infoLabels['thumbnail'] if item.infoLabels['fanart']: item.fanart = item.infoLabels['fanart'] if seekTmdb: - def search(otmdb_global, tipo_busqueda): - if item.infoLabels['season']: + def search(otmdb_global, search_type): + if item.infoLabels.get('season'): try: - numtemporada = int(item.infoLabels['season']) + seasonNumber = int(item.infoLabels['season']) except ValueError: logger.debug("The season number is not valid.") return -1 * len(item.infoLabels) @@ -275,15 +277,15 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None lock.acquire() if not otmdb_global or (item.infoLabels['tmdb_id'] and str(otmdb_global.result.get("id")) != item.infoLabels['tmdb_id']) \ - or (otmdb_global.texto_buscado and otmdb_global.texto_buscado != item.infoLabels['tvshowtitle']): + or (otmdb_global.searched_text and otmdb_global.searched_text != item.infoLabels['tvshowtitle']): if item.infoLabels['tmdb_id']: - otmdb_global = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda) + otmdb_global = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], search_type=search_type, + search_language=search_language) else: - otmdb_global = Tmdb(texto_buscado=scrapertools.unescape(item.infoLabels['tvshowtitle']), tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda, year=item.infoLabels['year']) + otmdb_global = Tmdb(searched_text=scrapertools.unescape(item.infoLabels['tvshowtitle']), search_type=search_type, + search_language=search_language, year=item.infoLabels['year']) - __leer_datos(otmdb_global) + read_data(otmdb_global) # 4l3x87 - fix for overlap infoLabels if there is episode or season # if lock and lock.locked(): @@ -291,7 +293,7 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None if item.infoLabels['episode']: try: - episode = int(item.infoLabels['episode']) + ep = int(item.infoLabels['episode']) except ValueError: logger.debug("The episode number (%s) is not valid" % repr(item.infoLabels['episode'])) return -1 * len(item.infoLabels) @@ -299,24 +301,24 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None # We have valid season number and episode number... # ... search episode data item.infoLabels['mediatype'] = 'episode' - episodio = otmdb_global.get_episodio(numtemporada, episode) + episode = otmdb_global.get_episode(seasonNumber, ep) - if episodio: + if episode: # Update data - __leer_datos(otmdb_global) - if episodio.get('episodio_titulo'): - item.infoLabels['title'] = episodio['episodio_titulo'] - if episodio.get('episodio_sinopsis'): - item.infoLabels['plot'] = episodio['episodio_sinopsis'] - if episodio.get('episodio_imagen'): - item.infoLabels['poster_path'] = episodio['episodio_imagen'] + read_data(otmdb_global) + if episode.get('episode_title'): + item.infoLabels['title'] = episode['episode_title'] + if episode.get('episode_plot'): + item.infoLabels['plot'] = episode['episode_plot'] + if episode.get('episode_image'): + item.infoLabels['poster_path'] = episode['episode_image'] item.thumbnail = item.infoLabels['poster_path'] - if episodio.get('episodio_air_date'): - item.infoLabels['aired'] = episodio['episodio_air_date'] - if episodio.get('episodio_vote_average'): - item.infoLabels['rating'] = episodio['episodio_vote_average'] - if episodio.get('episodio_vote_count'): - item.infoLabels['votes'] = episodio['episodio_vote_count'] + if episode.get('episode_air_date'): + item.infoLabels['aired'] = episode['episode_air_date'] + if episode.get('episode_vote_average'): + item.infoLabels['rating'] = episode['episode_vote_average'] + if episode.get('episode_vote_count'): + item.infoLabels['votes'] = episode['episode_vote_count'] # 4l3x87 - fix for overlap infoLabels if there is episode or season if lock and lock.locked(): @@ -328,21 +330,35 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None # We have a valid season number but no episode number... # ... search season data item.infoLabels['mediatype'] = 'season' - temporada = otmdb_global.get_temporada(numtemporada) - if not isinstance(temporada, dict): - temporada = ast.literal_eval(temporada.decode('utf-8')) + season = otmdb_global.get_season(seasonNumber) + enseason = otmdb_global.get_season(seasonNumber, language='en-US') + if not isinstance(season, dict): + season = ast.literal_eval(season.decode('utf-8')) + if not isinstance(enseason, dict): + enseason = ast.literal_eval(enseason.decode('utf-8')) - if temporada: + if season: # Update data - __leer_datos(otmdb_global) - item.infoLabels['title'] = temporada['name'] if 'name' in temporada else '' - if 'overview' in temporada and temporada['overview']: - item.infoLabels['plot'] = temporada['overview'] - if 'air_date' in temporada and temporada['air_date']: - date = temporada['air_date'].split('-') + read_data(otmdb_global) + seasonTitle = season.get("name", '') + seasonPlot = season.get("overview" , '') + seasonDate = season.get("air_date", '') + seasonPoster = season.get('poster_path', '') + + seasonTitleEN = enseason.get("name", '') + seasonPlotEN = enseason.get("overview" , '') + seasonDateEN = enseason.get("air_date", '') + seasonPosterEN = enseason.get('poster_path', '') + + item.infoLabels['title'] = seasonTitle if seasonTitle else seasonTitleEN if seasonTitleEN else config.get_localized_string(60027) % seasonNumber + item.infoLabels['plot'] = seasonPlot if seasonPlot else seasonPlotEN if seasonPlotEN else '' + date = seasonDate if seasonDate else seasonDateEN if seasonDateEN else '' + if date: + date.split('-') item.infoLabels['aired'] = date[2] + "/" + date[1] + "/" + date[0] - if 'poster_path' in temporada and temporada['poster_path']: - item.infoLabels['poster_path'] = 'https://image.tmdb.org/t/p/original' + temporada['poster_path'] + poster = seasonPoster if seasonPoster else seasonPosterEN if seasonPosterEN else '' + if poster: + item.infoLabels['poster_path'] = 'https://image.tmdb.org/t/p/original' + poster item.thumbnail = item.infoLabels['poster_path'] # 4l3x87 - fix for overlap infoLabels if there is episode or season @@ -361,62 +377,62 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None # Search by ID... if item.infoLabels['tmdb_id']: # ...Search for tmdb_id - otmdb = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda) + otmdb = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], search_type=search_type, + search_language=search_language) elif item.infoLabels['imdb_id']: # ...Search by imdb code - otmdb = Tmdb(external_id=item.infoLabels['imdb_id'], external_source="imdb_id", tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda) + otmdb = Tmdb(external_id=item.infoLabels['imdb_id'], external_source="imdb_id", search_type=search_type, + search_language=search_language) - elif tipo_busqueda == 'tv': # bsearch with other codes + elif search_type == 'tv': # bsearch with other codes if item.infoLabels['tvdb_id']: # ...Search for tvdb_id otmdb = Tmdb(external_id=item.infoLabels['tvdb_id'], external_source="tvdb_id", - tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda) + search_type=search_type, search_language=search_language) elif item.infoLabels['freebase_mid']: # ...Search for freebase_mid otmdb = Tmdb(external_id=item.infoLabels['freebase_mid'], external_source="freebase_mid", - tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda) + search_type=search_type, search_language=search_language) elif item.infoLabels['freebase_id']: # ...Search by freebase_id otmdb = Tmdb(external_id=item.infoLabels['freebase_id'], external_source="freebase_id", - tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda) + search_type=search_type, search_language=search_language) elif item.infoLabels['tvrage_id']: # ...Search by tvrage_id otmdb = Tmdb(external_id=item.infoLabels['tvrage_id'], external_source="tvrage_id", - tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda) + search_type=search_type, search_language=search_language) # if otmdb is None: if not item.infoLabels['tmdb_id'] and not item.infoLabels['imdb_id'] and not item.infoLabels['tvdb_id']\ and not item.infoLabels['freebase_mid'] and not item.infoLabels['freebase_id'] and not item.infoLabels['tvrage_id']: # Could not search by ID ... # do it by title - if tipo_busqueda == 'tv': + if search_type == 'tv': # Serial search by title and filtering your results if necessary - otmdb = Tmdb(texto_buscado=scrapertools.unescape(item.infoLabels['tvshowtitle']), tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda, filtro=item.infoLabels.get('filtro', {}), + otmdb = Tmdb(searched_text=scrapertools.unescape(item.infoLabels['tvshowtitle']), search_type=search_type, + search_language=search_language, filtro=item.infoLabels.get('filtro', {}), year=item.infoLabels['year']) else: # Movie search by title ... # if item.infoLabels['year'] or item.infoLabels['filtro']: # ...and year or filter searched_title = item.contentTitle if item.contentTitle else item.fulltitle - otmdb = Tmdb(texto_buscado=scrapertools.unescape(searched_title), tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda, + otmdb = Tmdb(searched_text=scrapertools.unescape(searched_title), search_type=search_type, search_language=search_language, filtro=item.infoLabels.get('filtro', {}), year=item.infoLabels['year']) if otmdb is not None: if otmdb.get_id() and config.get_setting("tmdb_plus_info", default=False): # If the search has been successful and you are not looking for a list of items, # carry out another search to expand the information - otmdb = Tmdb(id_Tmdb=otmdb.result.get("id"), tipo=tipo_busqueda, - idioma_busqueda=idioma_busqueda) + otmdb = Tmdb(id_Tmdb=otmdb.result.get("id"), search_type=search_type, + search_language=search_language) if lock and lock.locked(): lock.release() if otmdb is not None and otmdb.get_id(): # The search has found a valid result - __leer_datos(otmdb) + read_data(otmdb) return len(item.infoLabels) def unify(): @@ -428,16 +444,16 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None return True # We check what type of content it is... if item.contentType == 'movie': - tipo_busqueda = 'movie' + search_type = 'movie' elif item.contentType == 'undefined': # don't know - tipo_busqueda = 'multi' + search_type = 'multi' else: - tipo_busqueda = 'tv' + search_type = 'tv' - ret = search(otmdb_global, tipo_busqueda) + ret = search(otmdb_global, search_type) if not ret: # try with unified title if unify(): - ret = search(otmdb_global, tipo_busqueda) + ret = search(otmdb_global, search_type) return ret # Search in tmdb is deactivated or has not given result # item.contentType = item.infoLabels['mediatype'] @@ -451,12 +467,12 @@ def find_and_set_infoLabels(item): tmdb_result = None if item.contentType == "movie": - tipo_busqueda = "movie" - tipo_contenido = config.get_localized_string(60247) + search_type = "movie" + content_type = config.get_localized_string(60247) title = item.contentTitle else: - tipo_busqueda = "tv" - tipo_contenido = config.get_localized_string(60298) + search_type = "tv" + content_type = config.get_localized_string(60298) title = item.contentSerieName # If the title includes the (year) we will remove it @@ -467,15 +483,15 @@ def find_and_set_infoLabels(item): if not item.infoLabels.get("tmdb_id") or not item.infoLabels.get("tmdb_id")[0].isdigit(): if not item.infoLabels.get("imdb_id"): - otmdb_global = Tmdb(texto_buscado=scrapertools.unescape(title), tipo=tipo_busqueda, year=item.infoLabels['year']) + otmdb_global = Tmdb(searched_text=scrapertools.unescape(title), search_type=search_type, year=item.infoLabels['year']) else: - otmdb_global = Tmdb(external_id=item.infoLabels.get("imdb_id"), external_source="imdb_id", tipo=tipo_busqueda) + otmdb_global = Tmdb(external_id=item.infoLabels.get("imdb_id"), external_source="imdb_id", search_type=search_type) elif not otmdb_global or str(otmdb_global.result.get("id")) != item.infoLabels['tmdb_id']: - otmdb_global = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], tipo=tipo_busqueda, idioma_busqueda=def_lang) + otmdb_global = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], search_type=search_type, search_language=def_lang) - results = otmdb_global.get_list_resultados() + results = otmdb_global.get_list_results() if len(results) > 1: - tmdb_result = platformtools.show_video_info(results, item=item, caption= tipo_contenido % title) + tmdb_result = platformtools.show_video_info(results, item=item, caption= content_type % title) elif len(results) > 0: tmdb_result = results[0] @@ -487,9 +503,9 @@ def find_and_set_infoLabels(item): if tmdb_result: infoLabels['tmdb_id'] = tmdb_result['id'] # all look if it can be removed and get only from get_nfo () - infoLabels['url_scraper'] = ["https://www.themoviedb.org/%s/%s" % (tipo_busqueda, infoLabels['tmdb_id'])] + infoLabels['url_scraper'] = ["https://www.themoviedb.org/{}/{}".format(search_type, infoLabels['tmdb_id'])] if infoLabels['tvdb_id']: - infoLabels['url_scraper'].append("http://thetvdb.com/index.php?tab=series&id=%s" % infoLabels['tvdb_id']) + infoLabels['url_scraper'].append("http://thetvdb.com/index.php?tab=series&id=" + infoLabels['tvdb_id']) item.infoLabels = infoLabels set_infoLabels_item(item) @@ -532,7 +548,7 @@ def get_nfo(item, search_groups=False): else: return if "season" in item.infoLabels and "episode" in item.infoLabels: - info_nfo = "https://www.themoviedb.org/tv/%s/season/%s/episode/%s" % (item.infoLabels['tmdb_id'], item.contentSeason, item.contentEpisodeNumber) + info_nfo = "https://www.themoviedb.org/tv/{}/season/{}/episode/{}" .format(item.infoLabels['tmdb_id'], item.contentSeason, item.contentEpisodeNumber) else: info_nfo = ', '.join(item.infoLabels['url_scraper']) @@ -541,7 +557,7 @@ def get_nfo(item, search_groups=False): def get_groups(item): valid_groups = [] - url = 'https://api.themoviedb.org/3/tv/{}/episode_groups?api_key=a1ab8b8669da03637a4b98fa39c39228&language={}'.format(item.infoLabels['tmdb_id'], def_lang) + url = '{}/tv/{}/episode_groups?api_key={}&language={}'.format(host, item.infoLabels['tmdb_id'], api, def_lang) groups = requests.get(url).json().get('results',[]) for g in groups: @@ -563,7 +579,7 @@ def get_groups(item): def select_group(groups, item): selected = -1 - url = 'https://api.themoviedb.org/3/tv/{}?api_key=a1ab8b8669da03637a4b98fa39c39228&language={}'.format(item.infoLabels['tmdb_id'], def_lang) + url = '{}/tv/{}?api_key={}&language={}'.format(host, item.infoLabels['tmdb_id'], api, def_lang) res = requests.get(url).json() selections = [['Original',res.get('number_of_seasons',0), res.get('number_of_episodes',0), '', item.thumbnail]] ids = ['original'] @@ -580,7 +596,7 @@ def select_group(groups, item): def get_group(Id): # from core.support import dbg;dbg() - url = 'https://api.themoviedb.org/3/tv/episode_group/{}?api_key=a1ab8b8669da03637a4b98fa39c39228&language={}'.format(Id, def_lang) + url = '{}/tv/episode_group/{}?api_key={}&language={}'.format(host, Id, api, def_lang) group = requests.get(url).json().get('groups',[]) return group @@ -594,7 +610,7 @@ def completar_codigos(item): ob = Tvdb(imdb_id=item.infoLabels['imdb_id']) item.infoLabels['tvdb_id'] = ob.get_id() if item.infoLabels['tvdb_id']: - url_scraper = "http://thetvdb.com/index.php?tab=series&id=%s" % item.infoLabels['tvdb_id'] + url_scraper = "http://thetvdb.com/index.php?tab=series&id=" + item.infoLabels['tvdb_id'] if url_scraper not in item.infoLabels['url_scraper']: item.infoLabels['url_scraper'].append(url_scraper) @@ -606,7 +622,7 @@ def discovery(item, dict_=False, cast=False): listado = Tmdb(discover = dict_, cast=cast) elif item.search_type == 'discover': - listado = Tmdb(discover={'url':'discover/%s' % item.type, 'with_genres':item.list_type, 'language':def_lang, 'page':item.page}) + listado = Tmdb(discover={'url':'discover/' + item.type, 'with_genres':item.list_type, 'language':def_lang, 'page':item.page}) elif item.search_type == 'list': if item.page == '': @@ -615,11 +631,12 @@ def discovery(item, dict_=False, cast=False): return listado -def get_genres(type): +def get_dic_genres(search_type): lang = def_lang - genres = Tmdb(tipo=type) + # from core.support import dbg;dbg() + genres = Tmdb(search_type=search_type) - return genres.dic_generos[lang] + return genres.dic_genres[lang] # Auxiliary class @@ -688,12 +705,12 @@ class ResultDictDefault(dict): # Scraper for the API based addon from https://www.themoviedb.org/ # version 1.4: # - Documented limitation of API use (see below). -# - Added get_temporada () method +# - Added get_season () method # version 1.3: # - Fixed error when returning None the path_poster and backdrop_path # - Fixed a bug that caused the list of genres to accumulate from one call to another -# - Added get_generos () method -# - Added optional parameters alternative_language to the get_sinopsis () method +# - Added get_genres () method +# - Added optional parameters alternative_language to the get_plot () method # # # Usage: @@ -737,16 +754,16 @@ class ResultDictDefault(dict): # Main methods: # get_id (): Returns a str with the Tmdb identifier of the loaded movie or series or an empty string if there were no # nothing loaded. -# get_sinopsis (alternate_language): Returns a str with the synopsis of the series or movie loaded. +# get_plot (alternate_language): Returns a str with the synopsis of the series or movie loaded. # get_poster (response_type, size): Get the poster or a list of posters. # get_backdrop (response_type, size): Get a background image or a list of background images. -# get_temporada (season): Get a dictionary with season-specific data. -# get_episodio (season, episode): Get a dictionary with specific data of the episode. -# get_generos (): Returns a str with the list of genres to which the movie or series belongs. +# get_season (season): Get a dictionary with season-specific data. +# get_episode (season, episode): Get a dictionary with specific data of the episode. +# get_genres (): Returns a str with the list of genres to which the movie or series belongs. # # # Other methods: -# load_resultado (result, page): When the search returns several results we can select which result +# load_result (result, page): When the search returns several results we can select which result # concrete and from which page to load the data. # # Limitations: @@ -757,9 +774,9 @@ class ResultDictDefault(dict): class Tmdb(object): # Class attribute - dic_generos = {} + dic_genres = {} ''' - dic_generos={"id_idioma1": {"tv": {"id1": "name1", + dic_genres={"id_idioma1": {"tv": {"id1": "name1", "id2": "name2" }, "movie": {"id1": "name1", @@ -835,39 +852,40 @@ class Tmdb(object): self.total_pages = 0 self.total_results = 0 - self.temporada = {} - self.texto_buscado = kwargs.get('texto_buscado', '') + self.season = {} + self.searched_text = kwargs.get('searched_text', '') - self.busqueda_id = kwargs.get('id_Tmdb', '') - self.busqueda_texto = re.sub('\[\\\?(B|I|COLOR)\s?[^\]]*\]', '', self.texto_buscado).strip() - self.busqueda_tipo = kwargs.get('tipo', '') - self.busqueda_idioma = kwargs.get('idioma_busqueda', def_lang) - # self.busqueda_include_adult = kwargs.get('include_adult', False) - self.busqueda_year = kwargs.get('year', '') - self.busqueda_filtro = kwargs.get('filtro', {}) + self.search_id = kwargs.get('id_Tmdb', '') + self.search_text = re.sub('\[\\\?(B|I|COLOR)\s?[^\]]*\]', '', self.searched_text).strip() + self.search_type = kwargs.get('search_type', '') + self.search_language = kwargs.get('search_language', def_lang) + self.fallback_language = kwargs.get('search_language', 'en-US') + # self.search_include_adult = kwargs.get('include_adult', False) + self.search_year = kwargs.get('year', '') + self.search_filter = kwargs.get('filtro', {}) self.discover = kwargs.get('discover', {}) # Refill gender dictionary if necessary - if (self.busqueda_tipo == 'movie' or self.busqueda_tipo == "tv") and (self.busqueda_idioma not in Tmdb.dic_generos or self.busqueda_tipo not in Tmdb.dic_generos[self.busqueda_idioma]): - self.rellenar_dic_generos(self.busqueda_tipo, self.busqueda_idioma) + if (self.search_type == 'movie' or self.search_type == "tv") and (self.search_language not in Tmdb.dic_genres or self.search_type not in Tmdb.dic_genres[self.search_language]): + self.filling_dic_genres(self.search_type, self.search_language) - if not self.busqueda_tipo: - self.busqueda_tipo = 'movie' + if not self.search_type: + self.search_type = 'movie' - if self.busqueda_id: - #Search by tmdb identifier + if self.search_id: + # Search by tmdb identifier self.__by_id() - elif self.busqueda_texto: - # Busqueda por texto + elif self.search_text: + # Search by text self.__search(page=self.page) elif 'external_source' in kwargs and 'external_id' in kwargs: # Search by external identifier according to type. # TV Series: imdb_id, freebase_mid, freebase_id, tvdb_id, tvrage_id # Movies: imdb_id - if (self.busqueda_tipo == 'movie' and kwargs.get('external_source') == "imdb_id") or (self.busqueda_tipo == 'tv' and kwargs.get('external_source') in ("imdb_id", "freebase_mid", "freebase_id", "tvdb_id", "tvrage_id")): - self.busqueda_id = kwargs.get('external_id') + if (self.search_type == 'movie' and kwargs.get('external_source') == "imdb_id") or (self.search_type == 'tv' and kwargs.get('external_source') in ("imdb_id", "freebase_mid", "freebase_id", "tvdb_id", "tvrage_id")): + self.search_id = kwargs.get('external_id') self.__by_id(source=kwargs.get('external_source')) elif self.discover: @@ -912,24 +930,24 @@ class Tmdb(object): return dict_data @classmethod - def rellenar_dic_generos(cls, tipo='movie', idioma=def_lang): + def filling_dic_genres(cls, search_type='movie', language=def_lang): # Fill dictionary of genres of the type and language passed as parameters - if idioma not in cls.dic_generos: - cls.dic_generos[idioma] = {} + if language not in cls.dic_genres: + cls.dic_genres[language] = {} - if tipo not in cls.dic_generos[idioma]: - cls.dic_generos[idioma][tipo] = {} - url = ('http://api.themoviedb.org/3/genre/%s/list?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s' % (tipo, idioma)) + if search_type not in cls.dic_genres[language]: + cls.dic_genres[language][search_type] = {} + url = ('{}/genre/{}/list?api_key={}&language={}'.format(host, search_type, api, language)) try: logger.debug("[Tmdb.py] Filling in dictionary of genres") - resultado = cls.get_json(url) - if not isinstance(resultado, dict): - resultado = ast.literal_eval(resultado.decode('utf-8')) - lista_generos = resultado["genres"] + result = cls.get_json(url) + if not isinstance(result, dict): + result = ast.literal_eval(result.decode('utf-8')) + list_genres = result["genres"] - for i in lista_generos: - cls.dic_generos[idioma][tipo][str(i["id"])] = i["name"] + for i in list_genres: + cls.dic_genres[language][search_type][str(i["id"])] = i["name"] except: logger.error("Error generating dictionaries") import traceback @@ -938,81 +956,78 @@ class Tmdb(object): def __by_id(self, source='tmdb'): # from core.support import dbg;dbg() - if self.busqueda_id: + if self.search_id: if source == "tmdb": # http://api.themoviedb.org/3/movie/1924?api_key=a1ab8b8669da03637a4b98fa39c39228&language=es # &append_to_response=images,videos,external_ids,credits&include_image_language=es,null # http://api.themoviedb.org/3/tv/1407?api_key=a1ab8b8669da03637a4b98fa39c39228&language=es # &append_to_response=images,videos,external_ids,credits&include_image_language=es,null - url = ('http://api.themoviedb.org/3/%s/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s' - '&append_to_response=images,videos,external_ids,credits&include_image_language=%s,null' % - (self.busqueda_tipo, self.busqueda_id, self.busqueda_idioma, self.busqueda_idioma)) - buscando = "id_Tmdb: %s" % self.busqueda_id + url = ('{}/{}/{}?api_key={}&language={}&append_to_response=images,videos,external_ids,credits&include_image_language={},null'.format(host, self.search_type, self.search_id, api, self.search_language, self.search_language)) + searching = "id_Tmdb: " + self.search_id else: # http://api.themoviedb.org/3/find/%s?external_source=imdb_id&api_key=a1ab8b8669da03637a4b98fa39c39228 - url = ('http://api.themoviedb.org/3/find/%s?external_source=%s&api_key=a1ab8b8669da03637a4b98fa39c39228' - '&language=%s' % (self.busqueda_id, source, self.busqueda_idioma)) - buscando = "%s: %s" % (source.capitalize(), self.busqueda_id) + url = ('{}/find/{}?external_source={}&api_key={}8&language={}'.format(host, self.search_id, source, api, self.search_language)) + searching = "{}: {}".format(source.capitalize(), self.search_id) - logger.debug("[Tmdb.py] Searching %s:\n%s" % (buscando, url)) - resultado = self.get_json(url) - if not isinstance(resultado, dict): - resultado = ast.literal_eval(resultado.decode('utf-8')) + logger.debug("[Tmdb.py] Searching %s:\n%s" % (searching, url)) + result = self.get_json(url) + if not isinstance(result, dict): + result = ast.literal_eval(result.decode('utf-8')) - if resultado: + if result: if source != "tmdb": - if self.busqueda_tipo == "movie": - resultado = resultado["movie_results"][0] + if self.search_type == "movie": + result = result["movie_results"][0] else: - if resultado["tv_results"]: - resultado = resultado["tv_results"][0] + if result["tv_results"]: + result = result["tv_results"][0] else: - resultado = resultado['tv_episode_results'][0] + result = result['tv_episode_results'][0] - self.results = [resultado] + self.results = [result] self.total_results = 1 self.total_pages = 1 - self.result = ResultDictDefault(resultado) + self.result = ResultDictDefault(result) else: # No search results - msg = "The search of %s gave no results" % buscando + msg = "The search of %s gave no results" % searching logger.debug(msg) def __search(self, index_results=0, page=1): + # from core.support import dbg;dbg() self.result = ResultDictDefault() results = [] - text_simple = self.busqueda_texto.lower() + text_simple = self.search_text.lower() text_quote = urllib.quote(text_simple) total_results = 0 total_pages = 0 - buscando = "" + searching = "" - if self.busqueda_texto: + if self.search_text: # http://api.themoviedb.org/3/search/movie?api_key=a1ab8b8669da03637a4b98fa39c39228&query=superman&language=es # &include_adult=false&page=1 - url = ('http://api.themoviedb.org/3/search/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&query=%s&language=%s' - '&include_adult=%s&page=%s' % (self.busqueda_tipo, text_quote, self.busqueda_idioma, True, page)) + url = ('{}/search/{}?api_key={}&query={}&language={}&include_adult={}&page={}'.format(host, self.search_type, api, text_quote, self.search_language, True, page)) - if self.busqueda_year: - url += '&year=%s' % self.busqueda_year + if self.search_year: + url += '&year=%s' % self.search_year - buscando = self.busqueda_texto.capitalize() - logger.debug("[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')) + searching = self.search_text.capitalize() + logger.debug("[Tmdb.py] Searching %s on page %s:\n%s" % (searching, page, url)) + result = self.get_json(url) + if not isinstance(result, dict): + result = ast.literal_eval(result.decode('utf-8')) - total_results = resultado.get("total_results", 0) - total_pages = resultado.get("total_pages", 0) + total_results = result.get("total_results", 0) + total_pages = result.get("total_pages", 0) if total_results > 0: - results = [r for r in resultado["results"] if r.get('first_air_date', r.get('release_date', ''))] - # results = resultado["results"] + results = [r for r in result["results"] if r.get('first_air_date', r.get('release_date', ''))] + # results = result["results"] # logger.debug('RISULTATI', results) - if self.busqueda_filtro and total_results > 1: - for key, value in list(dict(self.busqueda_filtro).items()): + if self.search_filter and total_results > 1: + for key, value in list(dict(self.search_filter).items()): for r in results[:]: if not r[key]: r[key] = str(r[key]) @@ -1025,13 +1040,13 @@ class Tmdb(object): # A higher number of results has been requested than those obtained logger.error( "The search for '%s' gave %s results for the page %s \n It is impossible to show the result number %s" - % (buscando, len(results), page, index_results)) + % (searching, len(results), page, index_results)) return 0 # We sort result based on fuzzy match to detect most similar if len(results) > 1: from lib.fuzzy_match import algorithims - results.sort(key=lambda r: algorithims.trigram(text_simple, r.get('name', '') if self.busqueda_tipo == 'tv' else r.get('title', '')), reverse=True) + results.sort(key=lambda r: algorithims.trigram(text_simple, r.get('name', '') if self.search_type == 'tv' else r.get('title', '')), reverse=True) # We return the number of results of this page self.results = results @@ -1042,7 +1057,7 @@ class Tmdb(object): else: # No search results - msg = "The search for '%s' gave no results for page %s" % (buscando, page) + msg = "The search for '%s' gave no results for page %s" % (searching, page) logger.error(msg) return 0 @@ -1062,32 +1077,31 @@ class Tmdb(object): if key != "url": params.append(key + "=" + str(value)) # http://api.themoviedb.org/3/discover/movie?api_key=a1ab8b8669da03637a4b98fa39c39228&query=superman&language=es - url = ('http://api.themoviedb.org/3/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&%s' - % (type_search, "&".join(params))) + url = ('{}/{}?api_key={}&{}'.format(host, type_search, api, "&".join(params))) - logger.debug("[Tmdb.py] Searcing %s:\n%s" % (type_search, url)) - resultado = self.get_json(url, cache=False) - if not isinstance(resultado, dict): - resultado = ast.literal_eval(resultado.decode('utf-8')) + logger.debug("[Tmdb.py] Searching %s:\n%s" % (type_search, url)) + result = self.get_json(url, cache=False) + if not isinstance(result, dict): + result = ast.literal_eval(result.decode('utf-8')) - total_results = resultado.get("total_results", -1) - total_pages = resultado.get("total_pages", 1) + total_results = result.get("total_results", -1) + total_pages = result.get("total_pages", 1) if total_results > 0 or self.cast: if self.cast: - results = resultado[self.cast] + results = result[self.cast] total_results = len(results) else: - results = resultado["results"] - if self.busqueda_filtro and results: + results = result["results"] + if self.search_filter and results: # TODO documentar esta parte - for key, value in list(dict(self.busqueda_filtro).items()): + for key, value in list(dict(self.search_filter).items()): for r in results[:]: if key not in r or r[key] != value: results.remove(r) total_results -= 1 elif total_results == -1: - results = resultado + results = result if index_results >= len(results): logger.error( @@ -1110,7 +1124,7 @@ class Tmdb(object): logger.error("The search for '%s' gave no results" % type_search) return 0 - def load_resultado(self, index_results=0, page=1): + def load_result(self, index_results=0, page=1): # If there are no results, there is only one or if the number of results on this page is less than the index sought to exit self.result = ResultDictDefault() num_result_page = len(self.results) @@ -1129,7 +1143,7 @@ class Tmdb(object): self.result = ResultDictDefault(self.results[index_results]) return True - def get_list_resultados(self, num_result=20): + def get_list_results(self, num_result=20): # logger.debug("self %s" % str(self)) res = [] @@ -1142,7 +1156,7 @@ class Tmdb(object): for p in range(1, self.total_pages + 1): for r in range(0, len(self.results)): try: - if self.load_resultado(r, p): + if self.load_result(r, p): result = self.result.copy() result['thumbnail'] = self.get_poster(size="w300") @@ -1158,7 +1172,7 @@ class Tmdb(object): return res - def get_generos(self, origen=None): + def get_genres(self, origen=None): """ :param origen: Source dictionary where the infoLabels are obtained, by default self.result :type origen: Dict @@ -1174,7 +1188,7 @@ class Tmdb(object): # Search list of genres by IDs for i in origen.get("genre_ids"): try: - genre_list.append(Tmdb.dic_generos[self.busqueda_idioma][self.busqueda_tipo][str(i)]) + genre_list.append(Tmdb.dic_genres[self.search_language][self.search_type][str(i)]) except: pass @@ -1187,9 +1201,9 @@ class Tmdb(object): return ', '.join(genre_list) - def search_by_id(self, id, source='tmdb', tipo='movie'): - self.busqueda_id = id - self.busqueda_tipo = tipo + def search_by_id(self, id, source='tmdb', search_type='movie'): + self.search_id = id + self.search_type = search_type self.__by_id(source=source) def get_id(self): @@ -1199,12 +1213,12 @@ class Tmdb(object): """ return str(self.result.get('id', "")) - def get_sinopsis(self, idioma_alternativo=""): + def get_plot(self, language_alternative=''): """ - :param idioma_alternativo: Language code, according to ISO 639-1, if there is no synopsis in the language set for the search. + :param language_alternative: Language code, according to ISO 639-1, if there is no synopsis in the language set for the search. By default, the original language is used. If None is used as the alternative_language, it will only search in the set language. - :type idioma_alternativo: str + :type language_alternative: str :return: Returns the synopsis of a movie or series :rtype: str """ @@ -1213,22 +1227,22 @@ class Tmdb(object): if 'id' in self.result: ret = self.result.get('overview') - if ret == "" and str(idioma_alternativo).lower() != 'none': + if ret == "" and str(language_alternative).lower() != 'none': # Let's launch a search for id and reread the synopsis again - self.busqueda_id = str(self.result["id"]) - if idioma_alternativo: - self.busqueda_idioma = idioma_alternativo + self.search_id = str(self.result["id"]) + if language_alternative: + self.search_language = language_alternative else: - self.busqueda_idioma = self.result['original_language'] + self.search_language = self.result['original_language'] - url = ('http://api.themoviedb.org/3/%s/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s' % (self.busqueda_tipo, self.busqueda_id, self.busqueda_idioma)) + url = ('{}/{}/{}?api_key={}&language={}'.format(host, self.search_type, self.search_id, api, self.search_language)) - resultado = self.get_json(url) - if not isinstance(resultado, dict): - resultado = ast.literal_eval(resultado.decode('utf-8')) + result = self.get_json(url) + if not isinstance(result, dict): + result = ast.literal_eval(result.decode('utf-8')) - if 'overview' in resultado: - self.result['overview'] = resultado['overview'] + if 'overview' in result: + self.result['overview'] = result['overview'] ret = self.result['overview'] return ret @@ -1261,7 +1275,7 @@ class Tmdb(object): if len(self.result['images_posters']) == 0: # We are going to launch a search by id and reread again - self.busqueda_id = str(self.result["id"]) + self.search_id = str(self.result["id"]) self.__by_id() if len(self.result['images_posters']) > 0: @@ -1308,7 +1322,7 @@ class Tmdb(object): if len(self.result['images_backdrops']) == 0: # Let's launch a search by id and reread everything - self.busqueda_id = str(self.result["id"]) + self.search_id = str(self.result["id"]) self.__by_id() if len(self.result['images_backdrops']) > 0: @@ -1326,7 +1340,7 @@ class Tmdb(object): return ret - def get_temporada(self, numtemporada=1): + def get_season(self, seasonNumber=1, language=''): # -------------------------------------------------------------------------------------------------------------------------------------------- # Parameters: # season number: (int) Season number. Default 1. @@ -1336,46 +1350,46 @@ class Tmdb(object): # http://docs.themoviedb.apiary.io/#reference/tv-seasons/tvidseasonseasonnumber/get # http://docs.themoviedb.apiary.io/#reference/tv-seasons/tvidseasonseasonnumbercredits/get # -------------------------------------------------------------------------------------------------------------------------------------------- - if not self.result["id"] or self.busqueda_tipo != "tv": + if not self.result["id"] or self.search_type != "tv": return {} - numtemporada = int(numtemporada) - if numtemporada < 0: - numtemporada = 1 + seasonNumber = int(seasonNumber) + if seasonNumber < 0: + seasonNumber = 1 + search_language = language if language else self.search_language - if not self.temporada.get(numtemporada, {}): + if not self.season.get(seasonNumber, {}) or language: # If there is no information about the requested season, check the website # http://api.themoviedb.org/3/tv/1407/season/1?api_key=a1ab8b8669da03637a4b98fa39c39228&language=es& # append_to_response=credits - url = "http://api.themoviedb.org/3/tv/%s/season/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s" \ - "&append_to_response=credits" % (self.result["id"], numtemporada, self.busqueda_idioma) + url = "{}/tv/{}/season/{}?api_key={}&language={}&append_to_response=credits".format(host, self.result["id"], seasonNumber, api, search_language) logger.debug('TMDB URL', url) - buscando = "id_Tmdb: " + str(self.result["id"]) + " season: " + str(numtemporada) + "\nURL: " + url - logger.debug("[Tmdb.py] Searcing " + buscando) + searching = "id_Tmdb: " + str(self.result["id"]) + " season: " + str(seasonNumber) + "\nURL: " + url + logger.debug("[Tmdb.py] Searching " + searching) try: - self.temporada[numtemporada] = self.get_json(url) - if not isinstance(self.temporada[numtemporada], dict): - self.temporada[numtemporada] = ast.literal_eval(self.temporada[numtemporada].decode('utf-8')) + self.season[seasonNumber] = self.get_json(url) + if not isinstance(self.season[seasonNumber], dict): + self.season[seasonNumber] = ast.literal_eval(self.season[seasonNumber].decode('utf-8')) except: logger.error("Unable to get the season") - self.temporada[numtemporada] = {"status_code": 15, "status_message": "Failed"} - self.temporada[numtemporada] = {"episodes": {}} + self.season[seasonNumber] = {"status_code": 15, "status_message": "Failed"} + self.season[seasonNumber] = {"episodes": {}} - if "status_code" in self.temporada[numtemporada]: + if "status_code" in self.season[seasonNumber]: # An error has occurred - msg = config.get_localized_string(70496) + buscando + config.get_localized_string(70497) + msg = config.get_localized_string(70496) + searching + config.get_localized_string(70497) msg += "\nTmdb error: %s %s" % ( - self.temporada[numtemporada]["status_code"], self.temporada[numtemporada]["status_message"]) + self.season[seasonNumber]["status_code"], self.season[seasonNumber]["status_message"]) logger.debug(msg) - self.temporada[numtemporada] = {} + self.season[seasonNumber] = {} - return self.temporada[numtemporada] + return self.season[seasonNumber] - def get_episodio(self, numtemporada=1, capitulo=1): + def get_episode(self, seasonNumber=1, chapter=1): # -------------------------------------------------------------------------------------------------------------------------------------------- # Parameters: # season number (optional): (int) Season number. Default 1. @@ -1389,100 +1403,146 @@ class Tmdb(object): # With chapter == -1 the dictionary will only have the elements referring to the season # -------------------------------------------------------------------------------------------------------------------------------------------- - if not self.result["id"] or self.busqueda_tipo != "tv": + if not self.result["id"] or self.search_type != "tv": return {} try: - capitulo = int(capitulo) - numtemporada = int(numtemporada) + chapter = int(chapter) + seasonNumber = int(seasonNumber) except ValueError: logger.debug("The episode or season number is not valid") return {} - temporada = self.get_temporada(numtemporada) - if not isinstance(temporada, dict): - temporada = ast.literal_eval(temporada.decode('utf-8')) - if not temporada: + season = self.get_season(seasonNumber) + enseason = self.get_season(seasonNumber, language='en-US') + if not isinstance(season, dict): + season = ast.literal_eval(season.decode('utf-8')) + if not isinstance(enseason, dict): + enseason = ast.literal_eval(enseason.decode('utf-8')) + if not season and not enseason: # An error has occurred return {} - if len(temporada["episodes"]) == 0: + if len(season["episodes"]) == 0 and len(enseason["episodes"]) == 0: # An error has occurred - logger.error("Episode %d of the season %d not found." % (capitulo, numtemporada)) + logger.error("Episode %d of the season %d not found." % (chapter, seasonNumber)) return {} - elif len(temporada["episodes"]) < capitulo and temporada["episodes"][-1]['episode_number'] >= capitulo: + elif len(season["episodes"]) < chapter and season["episodes"][-1]['episode_number'] >= chapter: n = None - for i, chapters in enumerate(temporada["episodes"]): - if chapters['episode_number'] == capitulo: + for i, chapters in enumerate(season["episodes"]): + if chapters['episode_number'] == chapter: n = i + 1 break if n != None: - capitulo = n + chapter = n else: - logger.error("Episode %d of the season %d not found." % (capitulo, numtemporada)) + logger.error("Episode %d of the season %d not found." % (chapter, seasonNumber)) return {} - elif len(temporada["episodes"]) < capitulo: - logger.error("Episode %d of the season %d not found." % (capitulo, numtemporada)) + elif len(season["episodes"]) < chapter: + logger.error("Episode %d of the season %d not found." % (chapter, seasonNumber)) return {} ret_dic = dict() # Get data for this season - ret_dic["temporada_nombre"] = temporada["name"] - ret_dic["temporada_sinopsis"] = temporada["overview"] - ret_dic["temporada_id"] = temporada["id"] - ret_dic["temporada_num_episodios"] = len(temporada["episodes"]) - if temporada["air_date"]: - date = temporada["air_date"].split("-") - ret_dic["temporada_air_date"] = date[2] + "/" + date[1] + "/" + date[0] + seasonTitle = season.get("name", '') + seasonPlot = season.get("overview" , '') + seasonId = season.get("id", '') + seasonEpisodes = len(season.get("episodes",[])) + seasonDate = season.get("air_date", '') + seasonPoster = season.get('poster_path', '') + seasonCredits = season.get('credits', {}) + + seasonTitleEN = enseason.get("name", '') + seasonPlotEN = enseason.get("overview" , '') + seasonIdEN = enseason.get("id", '') + seasonEpisodesEN = len(enseason.get("episodes",[])) + seasonDateEN = enseason.get("air_date", '') + seasonPosterEN = enseason.get('poster_path', '') + seasonCreditsEN = enseason.get('credits', {}) + + ret_dic["season_title"] = seasonTitle if seasonTitle else seasonTitleEN if seasonTitleEN else config.get_localized_string(60027) % seasonNumber + ret_dic["season_plot"] = seasonPlot if seasonPlot else seasonPlotEN if seasonPlotEN else '' + ret_dic["season_id"] = seasonId if seasonId else seasonIdEN if seasonIdEN else '' + ret_dic["season_episodes_number"] = seasonEpisodes if seasonEpisodes else seasonEpisodesEN if seasonEpisodesEN else 0 + date = seasonDate if seasonDate else seasonDateEN if seasonDateEN else '' + if date: + date = date.split("-") + ret_dic["season_air_date"] = date[2] + "/" + date[1] + "/" + date[0] else: - ret_dic["temporada_air_date"] = "" - if temporada["poster_path"]: - ret_dic["temporada_poster"] = 'https://image.tmdb.org/t/p/original' + temporada["poster_path"] + ret_dic["season_air_date"] = '' + poster = seasonPoster if seasonPoster else seasonPosterEN if seasonPosterEN else '' + if poster: + ret_dic["season_poster"] = 'https://image.tmdb.org/t/p/original' + poster else: - ret_dic["temporada_poster"] = "" - dic_aux = temporada.get('credits', {}) - ret_dic["temporada_cast"] = dic_aux.get('cast', []) - ret_dic["temporada_crew"] = dic_aux.get('crew', []) - if capitulo == 0: + ret_dic["season_poster"] = '' + dic_aux = seasonCredits if seasonCredits else seasonCreditsEN if seasonCreditsEN else {} + ret_dic["season_cast"] = dic_aux.get('cast', []) + ret_dic["season_crew"] = dic_aux.get('crew', []) + if chapter == 0: # If we only look for season data, include the technical team that has intervened in any chapter - dic_aux = dict((i['id'], i) for i in ret_dic["temporada_crew"]) - for e in temporada["episodes"]: + dic_aux = dict((i['id'], i) for i in ret_dic["season_crew"]) + for e in season["episodes"]: for crew in e['crew']: if crew['id'] not in list(dic_aux.keys()): dic_aux[crew['id']] = crew - ret_dic["temporada_crew"] = list(dic_aux.values()) + ret_dic["season_crew"] = list(dic_aux.values()) # Obtain chapter data if applicable - if capitulo > 0: - episodio = temporada["episodes"][capitulo - 1] - ret_dic["episodio_titulo"] = episodio.get("name", ) - ret_dic["episodio_sinopsis"] = episodio["overview"] - if episodio["air_date"]: - date = episodio["air_date"].split("-") - ret_dic["episodio_air_date"] = date[2] + "/" + date[1] + "/" + date[0] + # from core.support import dbg;dbg() + if chapter > 0: + episode = season["episodes"][chapter - 1] + enepisode = enseason["episodes"][chapter - 1] + + episodeTitle = episode.get("name", '') + episodeId = episode.get('id', '') + episodePlot = episode.get('overview', '') + episodeDate = episode.get('air_date', '') + episodeImage = episode.get('still_path', '') + episodeCrew = episode.get('crew', []) + episodeStars = episode.get('guest_stars', []) + episodeVoteCount = episode.get('vote_count', 0) + episodeVoteAverage = episode.get('vote_average', 0) + + episodeTitleEN = enepisode.get("name", '') + episodeIdEN = enepisode.get('id', '') + episodePlotEN = enepisode.get('overview', '') + episodeDateEN = enepisode.get('air_date', '') + episodeImageEN = enepisode.get('still_path', '') + episodeCrewEN = enepisode.get('crew', []) + episodeStarsEN = enepisode.get('guest_stars', []) + episodeVoteCountEN = enepisode.get('vote_count', 0) + episodeVoteAverageEN = enepisode.get('vote_average', 0) + + ret_dic["episode_title"] = episodeTitle if episodeTitle and not episodeTitle.startswith(config.get_localized_string(70677)) else episodeTitleEN if episodeTitleEN and not episodeTitleEN.startswith('Episode') else episodeTitle if episodeTitle else '' + ret_dic["episode_plot"] = episodePlot if episodePlot else episodePlotEN if episodePlotEN else '' + date = episodeDate if episodeDate else episodeDateEN if episodeDateEN else '' + image = episodeImage if episodeImage else episodeImageEN if episodeImageEN else '' + if image: + ret_dic["episode_image"] = 'https://image.tmdb.org/t/p/original' + image else: - ret_dic["episodio_air_date"] = "" - ret_dic["episodio_crew"] = episodio["crew"] - ret_dic["episodio_guest_stars"] = episodio["guest_stars"] - ret_dic["episodio_vote_count"] = episodio["vote_count"] - ret_dic["episodio_vote_average"] = episodio["vote_average"] - ret_dic["episodio_id"] = episodio["id"] - if episodio["still_path"]: - ret_dic["episodio_imagen"] = 'https://image.tmdb.org/t/p/original' + episodio["still_path"] + ret_dic["episode_image"] = "" + if date: + date = date.split("-") + ret_dic["episode_air_date"] = date[2] + "/" + date[1] + "/" + date[0] else: - ret_dic["episodio_imagen"] = "" + ret_dic["episode_air_date"] = "" + ret_dic["episode_crew"] = episodeCrew if episodeCrew else episodeCrewEN if episodeCrewEN else [] + ret_dic["episode_guest_stars"] = episodeStars if episodeStars else episodeStarsEN if episodeStarsEN else [] + ret_dic["episode_vote_count"] = episodeVoteCount if episodeVoteCount else episodeVoteCountEN if episodeVoteCountEN else 0 + ret_dic["episode_vote_average"] = episodeVoteAverage if episodeVoteAverage else episodeVoteAverageEN if episodeVoteAverageEN else 0 + ret_dic["episode_id"] = episodeId if episodeId else episodeIdEN if episodeIdEN else '' return ret_dic def get_list_episodes(self): - url = 'https://api.themoviedb.org/3/tv/{id}?api_key=a1ab8b8669da03637a4b98fa39c39228&language={lang}'.format(id=self.busqueda_id, lang=self.busqueda_idioma) + url = '{}/tv/{}?api_key={}&language={}'.format(host=host, id=self.search_id, api=api, lang=self.search_language) results = requests.get(url).json().get('seasons', []) seasons = [] if results and 'Error' not in results: for season in results: - url = 'https://api.themoviedb.org/3/tv/{id}/season/{season}?api_key=a1ab8b8669da03637a4b98fa39c39228&language={lang}'.format(id=self.busqueda_id, season=season['season_number'], lang=self.busqueda_idioma) + url = '{host}/tv/{id}/season/{season}?api_key={api}&language={lang}'.format(host=host, id=self.search_id, season=season['season_number'], api=api, lang=self.search_language) try: start_from = requests.get(url).json()['episodes'][0]['episode_number'] except: start_from = 1 seasons.append({'season_number':season['season_number'], 'episode_count':season['episode_count'], 'start_from':start_from}) @@ -1499,8 +1559,7 @@ class Tmdb(object): self.result["videos"] = self.result["videos"]['results'] else: # First video search in the search language - url = "http://api.themoviedb.org/3/%s/%s/videos?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s" \ - % (self.busqueda_tipo, self.result['id'], self.busqueda_idioma) + url = "{}/{}/{}/videos?api_key={}&language={}".format(host, self.search_type, self.result['id'], api, self.search_language) dict_videos = self.get_json(url) if not isinstance(dict_videos, dict): @@ -1511,8 +1570,8 @@ class Tmdb(object): self.result["videos"] = dict_videos['results'] # If the search language is not English, do a second video search in English - if self.busqueda_idioma != 'en': - url = "http://api.themoviedb.org/3/%s/%s/videos?api_key=a1ab8b8669da03637a4b98fa39c39228" % (self.busqueda_tipo, self.result['id']) + if self.search_language != 'en': + url = "{}/{}/{}/videos?api_key={}".format(host, self.search_type, self.result['id'], api) dict_videos = self.get_json(url) if not isinstance(dict_videos, dict): @@ -1566,13 +1625,13 @@ class Tmdb(object): items = list(origen.items()) # Season / episode information - if ret_infoLabels['season'] and self.temporada.get(ret_infoLabels['season']): + if ret_infoLabels['season'] and self.season.get(ret_infoLabels['season']): # If there is data loaded for the indicated season episodio = -1 if ret_infoLabels['episode']: episodio = ret_infoLabels['episode'] - items.extend(list(self.get_episodio(ret_infoLabels['season'], episodio).items())) + items.extend(list(self.get_episode(ret_infoLabels['season'], episodio).items())) # logger.debug("ret_infoLabels" % ret_infoLabels) @@ -1589,7 +1648,7 @@ class Tmdb(object): if origen: ret_infoLabels['plot'] = v else: - ret_infoLabels['plot'] = self.get_sinopsis() + ret_infoLabels['plot'] = self.get_plot() elif k == 'runtime': # Duration for movies ret_infoLabels['duration'] = int(v) * 60 @@ -1638,7 +1697,7 @@ class Tmdb(object): ret_infoLabels['imdb_id'] = v['imdb_id'] elif k in ['genres', "genre_ids", "genre"]: - ret_infoLabels['genre'] = self.get_generos(origen) + ret_infoLabels['genre'] = self.get_genres(origen) elif k == 'name' or k == 'title': ret_infoLabels['title'] = v @@ -1646,7 +1705,7 @@ class Tmdb(object): elif k == 'production_companies': ret_infoLabels['studio'] = ", ".join(i['name'] for i in v) - elif k == 'credits_cast' or k == 'temporada_cast' or k == 'episodio_guest_stars': + elif k == 'credits_cast' or k == 'season_cast' or k == 'episode_guest_stars': dic_aux = dict((name, character) for (name, character) in l_castandrole) l_castandrole.extend([(p['name'], p.get('character', '') or p.get('character_name', '')) \ for p in v if 'name' in p and p['name'] not in list(dic_aux.keys())]) @@ -1673,7 +1732,7 @@ class Tmdb(object): pais = Tmdb.dic_country.get(i['iso_3166_1'], i['iso_3166_1']) l_country = list(set(l_country + [pais])) - elif k == 'credits_crew' or k == 'episodio_crew' or k == 'temporada_crew': + elif k == 'credits_crew' or k == 'episode_crew' or k == 'season_crew': for crew in v: if crew['job'].lower() == 'director': l_director = list(set(l_director + [crew['name']])) diff --git a/core/videolibrarytools.py b/core/videolibrarytools.py index 0b0a28b5..1c16fad0 100644 --- a/core/videolibrarytools.py +++ b/core/videolibrarytools.py @@ -585,10 +585,17 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True): # process local episodes local_episodes_path = '' - local_episodelist = [] update = False nfo_path = filetools.join(path, "tvshow.nfo") head_nfo, item_nfo = read_nfo(nfo_path) + local_episodelist = item_nfo.local_episodes_list if item_nfo.local_episodes_list else [] + + if config.get_setting('videolibrary_kodi'): + from platformcode.xbmc_videolibrary import check_db + for p in check_db(item_nfo.infoLabels['code']): + local_episodelist += get_local_content(p) + item_nfo.local_episodes_list = local_episodelist + filetools.write(nfo_path, head_nfo + item_nfo.tojson()) if item_nfo.update_last: local_episodes_path = item_nfo.local_episodes_path @@ -601,47 +608,7 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True): filetools.write(nfo_path, head_nfo + item_nfo.tojson()) if local_episodes_path: - from platformcode.xbmc_videolibrary import check_db, clean - # check if the local episodes are in the Kodi video library - if check_db(local_episodes_path): - local_episodelist += get_local_content(local_episodes_path) - clean_list = [] - for f in filetools.listdir(path): - match = scrapertools.find_single_match(f, r'[Ss]?(\d+)(?:x|_|\s+)?[Ee]?[Pp]?(\d+)') - if match: - ep = '%dx%02d' % (int(match[0]), int(match[1])) - if ep in local_episodelist: - del_file = filetools.join(path, f) - filetools.remove(del_file) - if f.endswith('strm'): - sep = '\\' if '\\' in path else '/' - clean_path = path[:-len(sep)] if path.endswith(sep) else path - clean_path = '%/' + clean_path.split(sep)[-1] + '/' + f - clean_list.append(clean_path) - clean_list.append(clean_path.replace('/','\\')) - - if clean_list: - clean(clean_list) - update = True - - if item_nfo.local_episodes_list: - difference = [x for x in item_nfo.local_episodes_list if (x not in local_episodelist)] - if len(difference) > 0: - clean_list = [] - for f in difference: - sep = '\\' if '\\' in local_episodes_path else '/' - clean_path = local_episodes_path[:-len(sep)] if local_episodes_path.endswith(sep) else local_episodes_path - clean_path = '%/' + clean_path.split(sep)[-1] + '/%' + f.replace('x','%') + '%' - clean_list.append(clean_path) - clean_list.append(clean_path.replace('/','\\')) - clean(clean_list) - update = True - - item_nfo.local_episodes_list = sorted(local_episodelist) - filetools.write(nfo_path, head_nfo + item_nfo.tojson()) - # the local episodes are not in the Kodi video library - else: - process_local_episodes(local_episodes_path, path) + process_local_episodes(local_episodes_path, path, local_episodelist) insertados = 0 sobreescritos = 0 @@ -930,24 +897,22 @@ def config_local_episodes_path(path, item, silent=False): return 0, local_episodes_path -def process_local_episodes(local_episodes_path, path): +def process_local_episodes(local_episodes_path, path, local_episodes_list): logger.debug() sub_extensions = ['.srt', '.sub', '.sbv', '.ass', '.idx', '.ssa', '.smi'] artwork_extensions = ['.jpg', '.jpeg', '.png'] extensions = sub_extensions + artwork_extensions - local_episodes_list = [] files_list = [] for root, folders, files in filetools.walk(local_episodes_path): for file in files: if os.path.splitext(file)[1] in extensions: continue season_episode = scrapertools.get_season_and_episode(file) - if season_episode == "": - continue - local_episodes_list.append(season_episode) - files_list.append(file) + if season_episode and season_episode not in local_episodes_list: + local_episodes_list.append(season_episode) + files_list.append(file) nfo_path = filetools.join(path, "tvshow.nfo") head_nfo, item_nfo = read_nfo(nfo_path) diff --git a/externalsearch.py b/externalsearch.py deleted file mode 100644 index 2b837e08..00000000 --- a/externalsearch.py +++ /dev/null @@ -1,80 +0,0 @@ -import xbmc, sys, xbmcgui, os -from platformcode import config, logger - -# incliuding folder libraries -librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) -sys.path.insert(0, librerias) - - -from core import tmdb -from core.item import Item - -def execute_search(): - """ - Gather the selected ListItem's attributes in order to compute the `Item` parameters - and perform the KOD's globalsearch. - Globalsearch will be executed specifing the content-type of the selected ListItem - - NOTE: this method needs the DBTYPE and TMDB_ID specified as ListItem's properties - """ - - # These following lines are commented and keep in the code just as reminder. - # In future, they could be used to filter the search outcome - - # ADDON: maybe can we know if the current windows is related to a specific addon? - # we could skip the ContextMenu if we already are in KOD's window - - tmdbid = xbmc.getInfoLabel('ListItem.Property(tmdb_id)') - mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') - title = xbmc.getInfoLabel('ListItem.Title') - year = xbmc.getInfoLabel('ListItem.Year') - imdb = xbmc.getInfoLabel('ListItem.IMDBNumber') - # folderPath = xbmc.getInfoLabel('Container.FolderPath') - # filePath = xbmc.getInfoLabel('ListItem.FileNameAndPath') - # logger.info("****") - # logger.info( xbmc.getCondVisibility("String.Contains(Container.FolderPath, 'plugin.video.kod')") ) - # logger.info( xbmc.getCondVisibility("String.Contains(ListItem.FileNameAndPath, 'plugin.video.kod')") ) - # logger.info( xbmc.getCondVisibility("String.IsEqual(ListItem.dbtype,tvshow)") ) - # logger.info( xbmc.getCondVisibility("String.IsEqual(ListItem.dbtype,movie)") ) - # logger.info("****") - - # visible = xbmc.getCondVisibility("!String.StartsWith(ListItem.FileNameAndPath, 'plugin://plugin.video.kod/') + [String.IsEqual(ListItem.dbtype,tvshow) | String.IsEqual(ListItem.dbtype,movie)]") - - logstr = "Selected ListItem is: 'IMDB: {}' - TMDB: {}' - 'Title: {}' - 'Year: {}'' - 'Type: {}'".format(imdb, tmdbid, title, year, mediatype) - logger.info(logstr) - - if not tmdbid and imdb: - logger.info('No TMDBid found. Try to get by IMDB') - it = Item(contentType= mediatype, infoLabels={'imdb_id' : imdb}) - tmdb.set_infoLabels(it) - tmdbid = it.infoLabels.get('tmdb_id', '') - - if not tmdbid: - logger.info('No TMDBid found. Try to get by Title/Year') - it = Item(contentTitle= title, contentType= mediatype, infoLabels={'year' : year}) - tmdb.set_infoLabels(it) - tmdbid = it.infoLabels.get('tmdb_id', '') - - - item = Item( - action="Search", - channel="globalsearch", - contentType= mediatype, - mode="search", - text= title, - type= mediatype, - infoLabels= { - 'tmdb_id': tmdbid, - 'year': year - }, - folder= False - ) - - logger.info("Invoking Item: {}".format(item.tostring())) - - itemurl = item.tourl() - xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + itemurl + ")") - - -if __name__ == '__main__': - execute_search() diff --git a/platformcode/autorenumber.py b/platformcode/autorenumber.py index 2a730d82..9047ad7c 100644 --- a/platformcode/autorenumber.py +++ b/platformcode/autorenumber.py @@ -178,6 +178,8 @@ class autorenumber(): if number: if not number in self.episodes: self.makelist() item.title = '{} - {}'.format(typo(self.episodes[number], 'bold'), item.title) + item.contentSeason = int(self.episodes[number].split('x')[0]) + item.contentEpisodeNumber = int(self.episodes[number].split('x')[1]) else: self.makelist() diff --git a/platformcode/contextmenu/contextmenu.json b/platformcode/contextmenu/contextmenu.json new file mode 100644 index 00000000..3acd6121 --- /dev/null +++ b/platformcode/contextmenu/contextmenu.json @@ -0,0 +1,5 @@ +[ + "platformcode.contextmenu.search", + "platformcode.contextmenu.tvshow_options", + "platformcode.contextmenu.trailer" +] \ No newline at end of file diff --git a/platformcode/contextmenu/search.py b/platformcode/contextmenu/search.py new file mode 100644 index 00000000..9dd82078 --- /dev/null +++ b/platformcode/contextmenu/search.py @@ -0,0 +1,127 @@ +import xbmc, sys, os +from platformcode import config, logger +import re +# incliuding folder libraries +librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) +sys.path.insert(0, librerias) + + +from core import tmdb +from core.item import Item + +addon_id = config.get_addon_core().getAddonInfo('id') +global item_is_coming_from_kod + + +def check_condition(): + global item_is_coming_from_kod + logger.debug('check item condition') + mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') + + folderPath = xbmc.getInfoLabel('Container.FolderPath') + filePath = xbmc.getInfoLabel('ListItem.Path') + fileNameAndPath = xbmc.getInfoLabel('ListItem.FileNameAndPath') + + logger.debug('Container:',folderPath ) + logger.debug('listitem mediatype:',mediatype ) + logger.debug('filenamepath:', fileNameAndPath ) + logger.info('filepath:', filePath ) + + item_is_coming_from_kod = addon_id in filePath + if not item_is_coming_from_kod: + videolibpath = config.get_setting("videolibrarypath") + if filePath.startswith(videolibpath): + pattern = re.compile("\[.*\][\\\/]?$") + item_is_coming_from_kod = pattern.search(filePath) + + if item_is_coming_from_kod: + logger.debug("item IS already managed by KOD") + + return mediatype + + +def get_menu_items(): + logger.debug('get menu item') + if check_condition(): + return [(config.get_localized_string(90003 if item_is_coming_from_kod else 90005), execute)] + else: + return [] + + +def execute(): + """ + Gather the selected ListItem's attributes in order to compute the `Item` parameters + and perform the KOD's globalsearch. + Globalsearch will be executed specifing the content-type of the selected ListItem + + NOTE: this method needs the DBTYPE and TMDB_ID specified as ListItem's properties + """ + + # These following lines are commented and keep in the code just as reminder. + # In future, they could be used to filter the search outcome + + # ADDON: maybe can we know if the current windows is related to a specific addon? + # we could skip the ContextMenu if we already are in KOD's window + + tmdbid = xbmc.getInfoLabel('ListItem.Property(tmdb_id)') + mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') + title = xbmc.getInfoLabel('ListItem.Title') + year = xbmc.getInfoLabel('ListItem.Year') + imdb = xbmc.getInfoLabel('ListItem.IMDBNumber') + + if mediatype in ('episode', 'season'): + mediatype = 'tvshow' + title = xbmc.getInfoLabel('ListItem.TVShowTitle') + + logstr = "Selected ListItem is: 'IMDB: {}' - TMDB: {}' - 'Title: {}' - 'Year: {}'' - 'Type: {}'".format(imdb, tmdbid, title, year, mediatype) + logger.info(logstr) + + if not tmdbid and imdb: + logger.info('No TMDBid found. Try to get by IMDB') + it = Item(contentType= mediatype, infoLabels={'imdb_id' : imdb}) + try: + tmdb.set_infoLabels(it) + tmdbid = it.infoLabels.get('tmdb_id', '') + except: + logger.info("Cannot find TMDB via imdb") + + if not tmdbid: + logger.info('No TMDBid found. Try to get by Title/Year') + it = Item(contentTitle= title, contentType= mediatype, infoLabels={'year' : year}) + try: + tmdb.set_infoLabels(it) + tmdbid = it.infoLabels.get('tmdb_id', '') + except: + logger.info("Cannot find TMDB via title/year") + + if not tmdbid: + # We can continue searching by 'title (year)' + logger.info( "No TMDB found, proceed with title/year:", title , "(" , year, ")" ) + + # User wants to search on other channels + logger.info("Search on other channels") + + item = Item( + action="from_context", + channel="search", + contentType= mediatype, + mode="search", + contextual= True, + text=title, + type= mediatype, + infoLabels= { + 'tmdb_id': tmdbid, + 'year': year, + 'mediatype': mediatype + }, + folder= False + ) + + logger.info("Invoking Item: ", item.tostring() ) + + itemurl = item.tourl() + xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + itemurl + ")") + + + + diff --git a/platformcode/contextmenu/trailer.py b/platformcode/contextmenu/trailer.py new file mode 100644 index 00000000..6ad64c31 --- /dev/null +++ b/platformcode/contextmenu/trailer.py @@ -0,0 +1,23 @@ +import xbmc + +from core.item import Item +from platformcode import config + + +def get_menu_items(): + return [(config.get_localized_string(60359), execute)] + + +def execute(): + tmdbid = xbmc.getInfoLabel('ListItem.Property(tmdb_id)') + year = xbmc.getInfoLabel('ListItem.Year') + mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') + title = xbmc.getInfoLabel('ListItem.Title') + if mediatype in ('episode', 'season'): + mediatype = 'tvshow' + title = xbmc.getInfoLabel('ListItem.TVShowTitle') + + item = Item(channel="trailertools", action="buscartrailer", search_title=title, contentType=mediatype, + year=year, contentTitle=title, contextual=True) + item.infoLabels['tmdb_id'] = tmdbid + xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")") diff --git a/platformcode/contextmenu/tvshow_options.py b/platformcode/contextmenu/tvshow_options.py new file mode 100644 index 00000000..fd501db8 --- /dev/null +++ b/platformcode/contextmenu/tvshow_options.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- +import xbmc, sys, xbmcgui, os, xbmcvfs, traceback +from platformcode import config, logger + +librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) +sys.path.insert(0, librerias) + +from core.item import Item +from lib.sambatools import libsmb as samba +from core import scrapertools, support + +path = '' +mediatype = '' + + +def exists(path, silent=False, vfs=True): + path = xbmc.translatePath(path) + try: + if vfs: + result = bool(xbmcvfs.exists(path)) + if not result and not path.endswith('/') and not path.endswith('\\'): + result = bool(xbmcvfs.exists(join(path, ' ').rstrip())) + return result + elif path.lower().startswith("smb://"): + return samba.exists(path) + else: + return os.path.exists(path) + except: + logger.error("ERROR when checking the path: %s" % path) + if not silent: + logger.error(traceback.format_exc()) + return False + + +def join(*paths): + list_path = [] + if paths[0].startswith("/"): + list_path.append("") + for path in paths: + if path: + list_path += path.replace("\\", "/").strip("/").split("/") + + if scrapertools.find_single_match(paths[0], r'(^\w+:\/\/)'): + return str("/".join(list_path)) + else: + return str(os.sep.join(list_path)) + + +def search_paths(Id): + records = execute_sql('SELECT idPath FROM tvshowlinkpath WHERE idShow LIKE "%s"' % Id) + if len(records) >= 1: + for record in records: + path_records = execute_sql('SELECT strPath FROM path WHERE idPath LIKE "%s"' % record[0]) + for path in path_records: + if config.get_setting('videolibrarypath') in path[0] and exists(join(path[0], 'tvshow.nfo')): + return path[0] + return '' + + +def execute_sql(sql): + logger.debug() + file_db = "" + records = None + + # We look for the archive of the video database according to the version of kodi + video_db = config.get_platform(True)['video_db'] + if video_db: + file_db = os.path.join(xbmc.translatePath("special://userdata/Database"), video_db) + + # alternative method to locate the database + if not file_db or not os.path.exists(file_db): + file_db = "" + for f in os.path.listdir(xbmc.translatePath("special://userdata/Database")): + path_f = os.path.join(xbmc.translatePath("special://userdata/Database"), f) + + if os.path.pathoos.pathols.isfile(path_f) and f.lower().startswith('myvideos') and f.lower().endswith('.db'): + file_db = path_f + break + + if file_db: + logger.debug("DB file: %s" % file_db) + conn = None + try: + import sqlite3 + conn = sqlite3.connect(file_db) + cursor = conn.cursor() + + logger.debug("Running sql: %s" % sql) + cursor.execute(sql) + conn.commit() + + records = cursor.fetchall() + if sql.lower().startswith("select"): + if len(records) == 1 and records[0][0] is None: + records = [] + + conn.close() + logger.debug("Query executed. Records: %s" % len(records)) + + except: + logger.error("Error executing sql query") + if conn: + conn.close() + + else: + logger.debug("Database not found") + + return records + + +def get_id(): + global mediatype + + mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') + if mediatype == 'tvshow': + dbid = xbmc.getInfoLabel('ListItem.DBID') + elif mediatype in ('season', 'episode'): + dbid = xbmc.getInfoLabel('ListItem.TvShowDBID') + else: + dbid = '' + return dbid + +def check_condition(): + # support.dbg() + global path + path = search_paths(get_id()) + return path + + +def get_menu_items(): + logger.debug('get menu item') + if check_condition(): + items = [(config.get_localized_string(70269), update)] + from core import videolibrarytools + nfo = path + 'tvshow.nfo' + item = videolibrarytools.read_nfo(nfo)[1] + if item: + item.nfo = nfo + item_url = item.tourl() + # Context menu: Automatically search for new episodes or not + if item.active and int(item.active) > 0: + update_text = config.get_localized_string(60022) + value = 0 + else: + update_text = config.get_localized_string(60023) + value = 1 + items.append((update_text, + lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&title={}&action=mark_tvshow_as_updatable&channel=videolibrary&active={})".format(item_url, update_text, str(value))))) + if item.local_episodes_path == "": + items.append((config.get_localized_string(80048), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&action=add_local_episodes&channel=videolibrary&path={})".format(item_url, path)))) + else: + items.append((config.get_localized_string(80049), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&action=remove_local_episodes&channel=videolibrary&path={})".format(item_url, path)))) + + # Context menu: Delete series / channel + channels_num = len(item.library_urls) + if channels_num > 1: + delete_text = config.get_localized_string(60024) + multichannel = True + else: + delete_text = config.get_localized_string(60025) + multichannel = False + items.append((delete_text, lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?{}&action=delete&channel=videolibrary&multichannel={}&path={})".format(item_url, str(multichannel), path)))) + # if config.get_setting('downloadenabled'): + # from core import videolibrarytools + # from core import filetools + # if xbmc.getInfoLabel('ListItem.FilenameAndPath'): + # item = Item().fromurl(filetools.read(xbmc.getInfoLabel('ListItem.FilenameAndPath'))) + # else: + # item = videolibrarytools.read_nfo(path + 'tvshow.nfo')[1] + # if item: + # item_url = item.tourl() + # + # Download movie + # if mediatype == "movie": + # items.append((config.get_localized_string(60354), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % (item_url, + # 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))) + # + # elif item.contentSerieName: + # Download series + # if mediatype == "tvshow" and item.action not in ['findvideos']: + # if item.channel == 'videolibrary': + # items.append((config.get_localized_string(60003), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % ( + # item_url, + # 'channel=downloads&action=save_download&unseen=true&from_channel=' + item.channel + '&from_action=' + item.action)))) + # items.append((config.get_localized_string(60355), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % ( + # item_url, + # 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))) + # items.append((config.get_localized_string(60357), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % ( + # item_url, + # 'channel=downloads&action=save_download&download=season&from_channel=' + item.channel + '&from_action=' + item.action)))) + # Download episode + # elif mediatype == "episode" and item.action in ['findvideos']: + # items.append((config.get_localized_string(60356), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % ( + # item_url, + # 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))) + # Download season + # elif mediatype == "season": + # items.append((config.get_localized_string(60357), lambda: xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?%s&%s)" % ( + # item_url, + # 'channel=downloads&action=save_download&download=season&from_channel=' + item.channel + '&from_action=' + item.action)))) + + return items + else: + return [] + + +def update(): + dbid = get_id() + path = search_paths(dbid) + if path: + item = Item(action="update_tvshow", channel="videolibrary", path=path) + # Why? I think it is not necessary, just commented + # item.tourl() + xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")") diff --git a/platformcode/infoplus.py b/platformcode/infoplus.py index 5d88445a..aed3fb78 100644 --- a/platformcode/infoplus.py +++ b/platformcode/infoplus.py @@ -107,7 +107,7 @@ class MainWindow(xbmcgui.WindowXMLDialog): Trailer(info) elif control_id in [IMAGES]: info = self.getControl(RECOMANDED).getSelectedItem() - images = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), tipo='movie' if mode == 'movie' else 'tv').result.get("images", {}) + images = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), search_type='movie' if mode == 'movie' else 'tv').result.get("images", {}) for key, value in list(images.items()): if not value: images.pop(key) ImagesWindow(tmdb = images).doModal() @@ -287,7 +287,7 @@ def Trailer(info): trailers_list = [] Type = info.getProperty('mediatype') if Type != "movie": Type = "tv" - trailers_list = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), tipo=Type).get_videos() + trailers_list = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), search_type=Type).get_videos() if trailers_list: for i, trailer in enumerate(trailers_list): item = xbmcgui.ListItem(trailer['name']) @@ -444,7 +444,7 @@ def get_recomendations(info): Type = info.getProperty('mediatype') if Type != "movie": Type = "tv" search = {'url': '%s/%s/recommendations' % (Type, info.getProperty('tmdb_id')), 'language': 'it', 'page': 1} - tmdb_res = tmdb.Tmdb(discover=search, tipo=Type, idioma_Search='it').results + tmdb_res = tmdb.Tmdb(discover=search, search_type=Type, idioma_Search='it').results for result in tmdb_res: if Type == 'movie': title = result.get("title", '') @@ -473,7 +473,7 @@ def get_cast(info): cast_list = [] actors_list = [] Type = "movie" if info.getProperty('mediatype') == 'movie' else 'tv' - otmdb = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), tipo=Type) + otmdb = tmdb.Tmdb(id_Tmdb=info.getProperty('tmdb_id'), search_type=Type) actors = otmdb.result.get("credits", {}).get("cast", []) cast = otmdb.result.get("credits", {}).get("crew", []) if Type == 'movie' else otmdb.result.get("created_by", []) for i, crew in enumerate(cast): diff --git a/platformcode/launcher.py b/platformcode/launcher.py index 25839355..da9379cc 100644 --- a/platformcode/launcher.py +++ b/platformcode/launcher.py @@ -33,8 +33,8 @@ def start(): def run(item=None): - # from core.support import dbg;dbg() logger.debug() + if not item: # Extract item from sys.argv if sys.argv[2]: diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index c8427ac9..8c87fb38 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -67,9 +67,18 @@ def dialog_multiselect(heading, _list, autoclose=0, preselect=[], useDetails=Fal def dialog_progress(heading, message): - dialog = xbmcgui.DialogProgress() - dialog.create(heading, message) - return dialog + if get_window() in ('WINDOW_HOME', 'WINDOW_SETTINGS_MENU', 'WINDOW_SETTINGS_INTERFACE', 'WINDOW_SKIN_SETTINGS', 'SKIN'): + # in widget, hide any progress + class Dummy(object): + def __getattr__(self, name): + def _missing(*args, **kwargs): + pass + return _missing + return Dummy() + else: + dialog = xbmcgui.DialogProgress() + dialog.create(heading, message) + return dialog def dialog_progress_bg(heading, message=""): @@ -177,6 +186,7 @@ def dialog_register(heading, user=False, email=False, password=False, user_defau dialog = Register('Register.xml', config.get_runtime_path()).Start(heading, user, email, password, user_default, email_default, password_default, captcha_img) return dialog + def dialog_info(item, scraper): class TitleOrIDWindow(xbmcgui.WindowXMLDialog): def Start(self, item, scraper): @@ -231,6 +241,7 @@ def dialog_info(item, scraper): dialog = TitleOrIDWindow('TitleOrIDWindow.xml', config.get_runtime_path()).Start(item, scraper) return dialog + def dialog_select_group(heading, _list, preselect=0): class SelectGroup(xbmcgui.WindowXMLDialog): def start(self, heading, _list, preselect): @@ -311,13 +322,6 @@ def render_items(itemlist, parent_item): default_fanart = config.get_fanart() def_context_commands = shortcuts.context() - # for adding extendedinfo to contextual menu, if it's used - has_extendedinfo = xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)') - # for adding superfavourites to contextual menu, if it's used - sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py") - check_sf = os.path.exists(sf_file_path) - superfavourites = check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")') - # if there's no item, add "no elements" item if not len(itemlist): itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png'))) @@ -332,8 +336,11 @@ def render_items(itemlist, parent_item): if not item.title: item.title = '' # If there is no action or it is findvideos / play, folder = False because no listing will be returned - if item.action in ['play', '']: - item.folder = False + if item.folder == "": # not set + if item.action in ['play', '']: + item.folder = False + else: + item.folder = True if item.fanart == "": item.fanart = parent_item.fanart if item.action == 'play' and thumb_type == 1 and not item.forcethumb: @@ -354,14 +361,13 @@ def render_items(itemlist, parent_item): listitem.setArt({'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail, 'fanart': item.fanart if item.fanart else default_fanart}) - if config.get_setting("player_mode") == 1 and item.action == "play" and not item.nfo: - listitem.setProperty('IsPlayable', 'true') + listitem.setProperty('IsPlayable', str(config.get_setting("player_mode") == 1 and item.action == "play" and not item.nfo).lower()) set_infolabels(listitem, item) # context menu if parent_item.channel != 'special': - context_commands = def_context_commands + set_context_commands(item, item_url, parent_item, has_extendedinfo=has_extendedinfo, superfavourites=superfavourites) + context_commands = def_context_commands + set_context_commands(item, item_url, parent_item) else: context_commands = def_context_commands listitem.addContextMenuItems(context_commands) @@ -388,6 +394,26 @@ def render_items(itemlist, parent_item): logger.debug('END render_items') +def viewmodeMonitor(): + try: + currentModeName = xbmc.getInfoLabel('Container.Viewmode') + win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) + currentMode = int(win.getFocusId()) + if currentModeName and 'plugin.video.kod' in xbmc.getInfoLabel('Container.FolderPath') and currentMode < 1000 and currentMode >= 50: # inside addon and in itemlist view + content, Type = getCurrentView() + if content: + defaultMode = int(config.get_setting('view_mode_%s' % content).split(',')[-1]) + if currentMode != defaultMode: + logger.debug('viewmode changed: ' + currentModeName + '-' + str(currentMode) + ' - content: ' + content) + config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode)) + dialog_notification(config.get_localized_string(70153), + config.get_localized_string(70187) % (content, currentModeName), + sound=False) + except: + import traceback + logger.error(traceback.print_exc()) + + def getCurrentView(item=None, parent_item=None): if not parent_item: info = xbmc.getInfoLabel('Container.FolderPath') @@ -395,7 +421,7 @@ def getCurrentView(item=None, parent_item=None): return None, None parent_item = Item().fromurl(info) if not item: - info = xbmc.getInfoLabel('Container.ListItem(1).FileNameAndPath') + info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath') # first addon listitem (consider "..") if not info: return None, None item = Item().fromurl(info) if info else Item() @@ -424,12 +450,12 @@ def getCurrentView(item=None, parent_item=None): return 'episode', 'tvshows' else: - return 'addon', 'addons' if config.get_setting('touch_view') else '' + return 'menu', 'addons' if config.get_setting('touch_view') else '' def set_view_mode(item, parent_item): def reset_view_mode(): - for mode in ['addon','channel','movie','tvshow','season','episode','server']: + for mode in ['menu','channel','movie','tvshow','season','episode','server']: config.set_setting('skin_name', xbmc.getSkinDir()) config.set_setting('view_mode_%s' % mode, config.get_localized_string(70003) + ' , 0') @@ -481,13 +507,13 @@ def set_infolabels(listitem, item, player=False): 'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'thumbnail': 'None', 'tvdb_id': 'None', 'tvshowtitle': 'tvshowtitle', 'type': 'None', 'userrating': 'userrating', 'url_scraper': 'None', 'votes': 'votes', 'writer': 'writer', 'year': 'year'} - if item.infoLabels: - try: - infoLabels_kodi = {infoLabels_dict[label_tag]: item.infoLabels[label_tag] for label_tag, label_value in list(item.infoLabels.items()) if infoLabels_dict[label_tag] != 'None'} - listitem.setInfo("video", infoLabels_kodi) - except: - listitem.setInfo("video", item.infoLabels) - # logger.error(item.infoLabels) + # if item.infoLabels: + try: + infoLabels_kodi = {infoLabels_dict[label_tag]: item.infoLabels[label_tag] for label_tag, label_value in list(item.infoLabels.items()) if infoLabels_dict[label_tag] != 'None'} + listitem.setInfo("video", infoLabels_kodi) + except: + listitem.setInfo("video", item.infoLabels) + # logger.error(item.infoLabels) def set_context_commands(item, item_url, parent_item, **kwargs): @@ -563,25 +589,6 @@ def set_context_commands(item, item_url, parent_item, **kwargs): # if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'): # context_commands.append((config.get_localized_string(60348), "Action(Info)")) - # ExtendedInfo: If the addon is installed and a series of conditions are met - if kwargs.get('has_extendedinfo') \ - and config.get_setting("extended_info") == True: - if item.contentType == "episode" and item.contentEpisodeNumber and item.contentSeason and (item.infoLabels['tmdb_id'] or item.contentSerieName): - param = "tvshow_id =%s, tvshow=%s, season=%s, episode=%s" % (item.infoLabels['tmdb_id'], item.contentSerieName, item.contentSeason, item.contentEpisodeNumber) - context_commands.append(("ExtendedInfo", "RunScript(script.extendedinfo,info=extendedepisodeinfo,%s)" % param)) - - elif item.contentType == "season" and item.contentSeason and (item.infoLabels['tmdb_id'] or item.contentSerieName): - param = "tvshow_id =%s,tvshow=%s, season=%s" % (item.infoLabels['tmdb_id'], item.contentSerieName, item.contentSeason) - context_commands.append(("ExtendedInfo", "RunScript(script.extendedinfo,info=seasoninfo,%s)" % param)) - - elif item.contentType == "tvshow" and (item.infoLabels['tmdb_id'] or item.infoLabels['tvdb_id'] or item.infoLabels['imdb_id'] or item.contentSerieName): - param = "id =%s,tvdb_id=%s,imdb_id=%s,name=%s" % (item.infoLabels['tmdb_id'], item.infoLabels['tvdb_id'], item.infoLabels['imdb_id'], item.contentSerieName) - context_commands.append(("ExtendedInfo", "RunScript(script.extendedinfo,info=extendedtvinfo,%s)" % param)) - - elif item.contentType == "movie" and (item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.contentTitle): - param = "id =%s,imdb_id=%s,name=%s" % (item.infoLabels['tmdb_id'], item.infoLabels['imdb_id'], item.contentTitle) - context_commands.append(("ExtendedInfo", "RunScript(script.extendedinfo,info=extendedinfo,%s)" % param)) - # InfoPlus if config.get_setting("infoplus"): #if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \ @@ -591,8 +598,6 @@ def set_context_commands(item, item_url, parent_item, **kwargs): # Open in browser and previous menu if parent_item.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist" and not parent_item.noMainMenu: - if parent_item.action != "mainlist": - context_commands.insert(0, (config.get_localized_string(60349), "Container.Refresh (%s?%s)" % (sys.argv[0], Item(channel=item.channel, action="mainlist").tourl()))) context_commands.insert(1, (config.get_localized_string(70739), "Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl()))) # Add to kodfavoritos (My links) @@ -635,7 +640,7 @@ def set_context_commands(item, item_url, parent_item, **kwargs): context_commands.append((config.get_localized_string(60354), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action))) elif item.contentSerieName: - # Descargar series + # Download series if item.contentType == "tvshow" and item.action not in ['findvideos']: if item.channel == 'videolibrary': context_commands.append((config.get_localized_string(60003), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=downloads&action=save_download&unseen=true&from_channel=' + item.channel + '&from_action=' + item.action))) @@ -652,9 +657,6 @@ def set_context_commands(item, item_url, parent_item, **kwargs): if (item.contentTitle and item.contentType in ['movie', 'tvshow']) or "buscar_trailer" in context: context_commands.append((config.get_localized_string(60359), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({ 'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.contentTitle if item.contentTitle else item.fulltitle, 'contextual': True})))) - if kwargs.get('superfavourites'): - context_commands.append((config.get_localized_string(60361), "RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)")) - if config.dev_mode(): context_commands.insert(0, ("item info", "Container.Update (%s?%s)" % (sys.argv[0], Item(action="itemInfo", parent=item.tojson()).tourl()))) return context_commands @@ -664,6 +666,265 @@ def is_playing(): return xbmc_player.isPlaying() +def get_window(): + """ + Return if addon is used as widget + For doing so, it check current window ID (https://kodi.wiki/view/Window_IDs) + """ + winId = xbmcgui.getCurrentWindowId() + if winId == 9999: + return 'WINDOW_INVALID' + elif winId == 10000: + return 'WINDOW_HOME' + elif winId == 10001: + return 'WINDOW_PROGRAMS' + elif winId == 10002: + return 'WINDOW_PICTURES' + elif winId == 10003: + return 'WINDOW_FILES' + elif winId == 10004: + return 'WINDOW_SETTINGS_MENU' + elif winId == 10007: + return 'WINDOW_SYSTEM_INFORMATION' + elif winId == 10011: + return 'WINDOW_SCREEN_CALIBRATION' + + elif winId == 10016: + return 'WINDOW_SETTINGS_START' + elif winId == 10016: + return 'WINDOW_SETTINGS_SYSTEM' + elif winId == 10018: + return 'WINDOW_SETTINGS_SERVICE' + + elif winId == 10021: + return 'WINDOW_SETTINGS_MYPVR' + elif winId == 10022: + return 'WINDOW_SETTINGS_MYGAMES' + + elif winId == 10025: + return 'WINDOW_VIDEO_NAV' + elif winId == 10028: + return 'WINDOW_VIDEO_PLAYLIST' + + elif winId == 10029: + return 'WINDOW_LOGIN_SCREEN' + + elif winId == 10030: + return 'WINDOW_SETTINGS_PLAYER' + elif winId == 10031: + return 'WINDOW_SETTINGS_MEDIA' + elif winId == 10032: + return 'WINDOW_SETTINGS_INTERFACE' + + elif winId == 10034: + return 'WINDOW_SETTINGS_PROFILES' + elif winId == 10035: + return 'WINDOW_SKIN_SETTINGS' + + elif winId == 10040: + return 'WINDOW_ADDON_BROWSER' + + elif winId == 10050: + return 'WINDOW_EVENT_LOG' + + elif winId == 97: + return 'WINDOW_SCREENSAVER_DIM' + elif winId == 98: + return 'WINDOW_DEBUG_INFO' + elif winId == 10099: + return 'WINDOW_DIALOG_POINTER' + elif winId == 10100: + return 'WINDOW_DIALOG_YES_NO' + elif winId == 10101: + return 'WINDOW_DIALOG_PROGRESS' + elif winId == 10103: + return 'WINDOW_DIALOG_KEYBOARD' + elif winId == 10104: + return 'WINDOW_DIALOG_VOLUME_BAR' + elif winId == 10105: + return 'WINDOW_DIALOG_SUB_MENU' + elif winId == 10106: + return 'WINDOW_DIALOG_CONTEXT_MENU' + elif winId == 10107: + return 'WINDOW_DIALOG_KAI_TOAST' + elif winId == 10109: + return 'WINDOW_DIALOG_NUMERIC' + elif winId == 10110: + return 'WINDOW_DIALOG_GAMEPAD' + elif winId == 10111: + return 'WINDOW_DIALOG_BUTTON_MENU' + elif winId == 10114: + return 'WINDOW_DIALOG_PLAYER_CONTROLS' + elif winId == 10115: + return 'WINDOW_DIALOG_SEEK_BAR' + elif winId == 10116: + return 'WINDOW_DIALOG_PLAYER_PROCESS_INFO' + elif winId == 10120: + return 'WINDOW_DIALOG_MUSIC_OSD' + elif winId == 10121: + return 'WINDOW_DIALOG_VIS_SETTINGS' + elif winId == 10122: + return 'WINDOW_DIALOG_VIS_PRESET_LIST' + elif winId == 10123: + return 'WINDOW_DIALOG_VIDEO_OSD_SETTINGS' + elif winId == 10124: + return 'WINDOW_DIALOG_AUDIO_OSD_SETTINGS' + elif winId == 10125: + return 'WINDOW_DIALOG_VIDEO_BOOKMARKS' + elif winId == 10126: + return 'WINDOW_DIALOG_FILE_BROWSER' + elif winId == 10128: + return 'WINDOW_DIALOG_NETWORK_SETUP' + elif winId == 10129: + return 'WINDOW_DIALOG_MEDIA_SOURCE' + elif winId == 10130: + return 'WINDOW_DIALOG_PROFILE_SETTINGS' + elif winId == 10131: + return 'WINDOW_DIALOG_LOCK_SETTINGS' + elif winId == 10132: + return 'WINDOW_DIALOG_CONTENT_SETTINGS' + elif winId == 10133: + return 'WINDOW_DIALOG_LIBEXPORT_SETTINGS' + elif winId == 10134: + return 'WINDOW_DIALOG_FAVOURITES' + elif winId == 10135: + return 'WINDOW_DIALOG_SONG_INFO' + elif winId == 10136: + return 'WINDOW_DIALOG_SMART_PLAYLIST_EDITOR' + elif winId == 10137: + return 'WINDOW_DIALOG_SMART_PLAYLIST_RULE' + elif winId == 10138: + return 'WINDOW_DIALOG_BUSY' + elif winId == 10139: + return 'WINDOW_DIALOG_PICTURE_INFO' + elif winId == 10140: + return 'WINDOW_DIALOG_ADDON_SETTINGS' + elif winId == 10142: + return 'WINDOW_DIALOG_FULLSCREEN_INFO' + elif winId == 10145: + return 'WINDOW_DIALOG_SLIDER' + elif winId == 10146: + return 'WINDOW_DIALOG_ADDON_INFO' + elif winId == 10147: + return 'WINDOW_DIALOG_TEXT_VIEWER' + elif winId == 10148: + return 'WINDOW_DIALOG_PLAY_EJECT' + elif winId == 10149: + return 'WINDOW_DIALOG_PERIPHERALS' + elif winId == 10150: + return 'WINDOW_DIALOG_PERIPHERAL_SETTINGS' + elif winId == 10151: + return 'WINDOW_DIALOG_EXT_PROGRESS' + elif winId == 10152: + return 'WINDOW_DIALOG_MEDIA_FILTER' + elif winId == 10153: + return 'WINDOW_DIALOG_SUBTITLES' + elif winId == 10156: + return 'WINDOW_DIALOG_KEYBOARD_TOUCH' + elif winId == 10157: + return 'WINDOW_DIALOG_CMS_OSD_SETTINGS' + elif winId == 10158: + return 'WINDOW_DIALOG_INFOPROVIDER_SETTINGS' + elif winId == 10159: + return 'WINDOW_DIALOG_SUBTITLE_OSD_SETTINGS' + elif winId == 10160: + return 'WINDOW_DIALOG_BUSY_NOCANCEL' + + elif winId == 10500: + return 'WINDOW_MUSIC_PLAYLIST' + elif winId == 10502: + return 'WINDOW_MUSIC_NAV' + elif winId == 10503: + return 'WINDOW_MUSIC_PLAYLIST_EDITOR' + + elif winId == 10550: + return 'WINDOW_DIALOG_OSD_TELETEXT' + + # PVR related Window and Dialog ID's + + elif 10600 < winId < 10613: + return 'WINDOW_DIALOG_PVR' + + + elif 10700 < winId < 10711: + return 'WINDOW_PVR_ID' + + # virtual windows for PVR specific keymap bindings in fullscreen playback + elif winId == 10800: + return 'WINDOW_FULLSCREEN_LIVETV' + elif winId == 10801: + return 'WINDOW_FULLSCREEN_RADIO' + elif winId == 10802: + return 'WINDOW_FULLSCREEN_LIVETV_PREVIEW' + elif winId == 10803: + return 'WINDOW_FULLSCREEN_RADIO_PREVIEW' + elif winId == 10804: + return 'WINDOW_FULLSCREEN_LIVETV_INPUT' + elif winId == 10805: + return 'WINDOW_FULLSCREEN_RADIO_INPUT' + + elif winId == 10820: + return 'WINDOW_DIALOG_GAME_CONTROLLERS' + elif winId == 10821: + return 'WINDOW_GAMES' + elif winId == 10822: + return 'WINDOW_DIALOG_GAME_OSD' + elif winId == 10823: + return 'WINDOW_DIALOG_GAME_VIDEO_FILTER' + elif winId == 10824: + return 'WINDOW_DIALOG_GAME_STRETCH_MODE' + elif winId == 10825: + return 'WINDOW_DIALOG_GAME_VOLUME' + elif winId == 10826: + return 'WINDOW_DIALOG_GAME_ADVANCED_SETTINGS' + elif winId == 10827: + return 'WINDOW_DIALOG_GAME_VIDEO_ROTATION' + elif 11100 < winId < 11199: + return 'SKIN' # WINDOW_ID's from 11100 to 11199 reserved for Skins + + elif winId == 12000: + return 'WINDOW_DIALOG_SELECT' + elif winId == 12001: + return 'WINDOW_DIALOG_MUSIC_INFO' + elif winId == 12002: + return 'WINDOW_DIALOG_OK' + elif winId == 12003: + return 'WINDOW_DIALOG_VIDEO_INFO' + elif winId == 12005: + return 'WINDOW_FULLSCREEN_VIDEO' + elif winId == 12006: + return 'WINDOW_VISUALISATION' + elif winId == 12007: + return 'WINDOW_SLIDESHOW' + elif winId == 12600: + return 'WINDOW_WEATHER' + elif winId == 12900: + return 'WINDOW_SCREENSAVER' + elif winId == 12901: + return 'WINDOW_DIALOG_VIDEO_OSD' + + elif winId == 12902: + return 'WINDOW_VIDEO_MENU' + elif winId == 12905: + return 'WINDOW_VIDEO_TIME_SEEK' # virtual window for time seeking during fullscreen video + + elif winId == 12906: + return 'WINDOW_FULLSCREEN_GAME' + + elif winId == 12997: + return 'WINDOW_SPLASH' # splash window + elif winId == 12998: + return 'WINDOW_START' # first window to load + elif winId == 12999: + return 'WINDOW_STARTUP_ANIM' # for startup animations + + elif 13000 < winId < 13099: + return 'PYTHON' # WINDOW_ID's from 13000 to 13099 reserved for Python + + elif 14000 < winId < 14099: + return 'ADDON' # WINDOW_ID's from 14000 to 14099 reserved for Addons + + def play_video(item, strm=False, force_direct=False, autoplay=False): logger.debug() logger.debug(item.tostring('\n')) diff --git a/platformcode/shortcuts.py b/platformcode/shortcuts.py index 6a7197bc..7e21b3f7 100644 --- a/platformcode/shortcuts.py +++ b/platformcode/shortcuts.py @@ -11,7 +11,7 @@ def context(): # pre-serialised if config.get_setting('quick_menu'): context.append((config.get_localized_string(60360), 'RunPlugin(plugin://plugin.video.kod/?ewogICAgImFjdGlvbiI6ICJzaG9ydGN1dF9tZW51IiwgCiAgICAiY2hhbm5lbCI6ICJzaG9ydGN1dHMiLCAKICAgICJpbmZvTGFiZWxzIjoge30KfQ%3D%3D)')) - if config.get_setting('kod_menu'): context.append((config.get_localized_string(60026), 'RunPlugin(plugin://plugin.video.kod/?ewogICAgImFjdGlvbiI6ICJzZXR0aW5nc19tZW51IiwgCiAgICAiY2hhbm5lbCI6ICJzaG9ydGN1dHMiLCAKICAgICJpbmZvTGFiZWxzIjoge30KfQ%3D%3D)')) + # if config.get_setting('kod_menu'): context.append((config.get_localized_string(60026), 'RunPlugin(plugin://plugin.video.kod/?ewogICAgImFjdGlvbiI6ICJzZXR0aW5nc19tZW51IiwgCiAgICAiY2hhbm5lbCI6ICJzaG9ydGN1dHMiLCAKICAgICJpbmZvTGFiZWxzIjoge30KfQ%3D%3D)')) return context diff --git a/platformcode/xbmc_videolibrary.py b/platformcode/xbmc_videolibrary.py index bbb221f8..9fcae0bf 100644 --- a/platformcode/xbmc_videolibrary.py +++ b/platformcode/xbmc_videolibrary.py @@ -1072,18 +1072,15 @@ def clean(path_list=[]): progress.close() -def check_db(path): - if '\\' in path: sep = '\\' - else: sep = '/' - if path.endswith(sep): path = path[:-len(sep)] - ret = False - sql_path = '%' + sep + path.split(sep)[-1] + sep + '%' - sql = 'SELECT idShow FROM tvshow_view where strPath LIKE "%s"' % sql_path - logger.debug('sql: ' + sql) - nun_records, records = execute_sql_kodi(sql) - if records: - ret = True - return ret +def check_db(code): + path_list = [] + for _id in code: + sql = 'SELECT strPath FROM tvshow_view where uniqueid_value = "%s"' % _id.replace('tmdb_','').replace('tvdb_','') + logger.debug('sql: ' + sql) + nun_records, records = execute_sql_kodi(sql) + if records: + path_list += [xbmc.translatePath(r[0]) for r in records] + return path_list def execute_sql_kodi(sql): diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 39947634..0c59e78d 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -3433,7 +3433,7 @@ msgid "Show ExtendedInfo" msgstr "" msgctxt "#70153" -msgid "" +msgid "View mode saved" msgstr "" msgctxt "#70154" @@ -3569,7 +3569,7 @@ msgid "Getting episodes..." msgstr "" msgctxt "#70187" -msgid "" +msgid "For content %s -> %s" msgstr "" msgctxt "#70188" @@ -6481,5 +6481,21 @@ msgid "Downloading..." msgstr "" msgctxt "#90001" +msgid "KOD options" +msgstr "KOD options..." + +msgctxt "#90002" +msgid "No TMDB found" +msgstr "No TmdbId found, cannot continue" + +msgctxt "#90003" +msgid "Already on KOD, continue searching on other channels?" +msgstr "Item is coming from KOD, continue searching on other channels?" + +msgctxt "#90004" +msgid "No contextmenu option" +msgstr "No options" + +msgctxt "#90005" msgid "Search on KOD" -msgstr "Search on KOD..." +msgstr "Search with KOD" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index 307be3f8..0163f562 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -3432,8 +3432,8 @@ msgid "Show ExtendedInfo" msgstr "Mostra ExtendedInfo" msgctxt "#70153" -msgid "" -msgstr "" +msgid "View mode saved" +msgstr "Tipo di vista salvato" msgctxt "#70154" msgid "TMDB search" @@ -3568,8 +3568,8 @@ msgid "Getting episodes..." msgstr "Ottenimento episodi..." msgctxt "#70187" -msgid "" -msgstr "" +msgid "For content %s -> %s" +msgstr "Per contenuto %s -> %s" msgctxt "#70188" msgid "Obtaining data for the TV show" @@ -6481,7 +6481,22 @@ msgctxt "#80050" msgid "Downloading..." msgstr "Download in corso..." - msgctxt "#90001" +msgid "KOD options" +msgstr "Opzioni di KOD..." + +msgctxt "#90002" +msgid "No TMDB found" +msgstr "Non sono riuscito a trovare le informazioni su TMDB" + +msgctxt "#90003" +msgid "Already on KOD, continue searching on other channels?" +msgstr "Preferisci cercare su altri canali?" + +msgctxt "#90004" +msgid "No contextmenu option" +msgstr "Nessuna opzione possibile" + +msgctxt "#90005" msgid "Search on KOD" -msgstr "Cerca con KOD..." +msgstr "Cerca con KOD" diff --git a/resources/settings.xml b/resources/settings.xml index 880344eb..5399e071 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -138,7 +138,7 @@ <setting id="touch_view" label='30002' type="bool" default="false"/> <!-- View Mode (hidden)--> <setting id="skin_name" label='Skin Name' type="text" default="skin.estuary" visible="false"/> - <setting id="view_mode_addon" type="action" label="70009" default= "Default, 0" visible="false"/> + <setting id="view_mode_menu" type="action" label="70009" default= "Default, 0" visible="false"/> <setting id="view_mode_channel" type="action" label="30118" default= "Default, 0" visible="false"/> <setting id="view_mode_movie" type="action" label="30122" default= "Default, 0" visible="false"/> <setting id="view_mode_tvshow" type="action" label="30123" default= "Default, 0" visible="false"/> @@ -149,7 +149,7 @@ <setting label="30024" type="lsep"/> <setting id="quick_menu" type="bool" label="60360" default="true"/> <!-- <setting id="side_menu" type="bool" label="70737" default="false"/> --> - <setting id="kod_menu" type="bool" label="60026" default="true"/> +<!-- <setting id="kod_menu" type="bool" label="60026" default="true"/>--> <setting id="infoplus" type="bool" label="70151" default="false"/> <!-- <setting id="infoplus_set" type="bool" label="70128" visible="eq(-1,true)" default="false" subsetting="true"/> --> <setting id="extended_info" type="bool" label="70152" default="false"/> diff --git a/servers/fembed.py b/servers/fembed.py index 45e6e28f..c7d65aad 100644 --- a/servers/fembed.py +++ b/servers/fembed.py @@ -10,11 +10,14 @@ def test_video_exists(page_url): global data # page_url = re.sub('://[^/]+/', '://feurl.com/', page_url) - data = httptools.downloadpage(page_url).data + page = httptools.downloadpage(page_url) + data = page.data if "Sorry 404 not found" in data or "This video is unavailable" in data or "Sorry this video is unavailable:" in data: return False, config.get_localized_string(70449) % "fembed" - page_url = page_url.replace("/f/","/v/") - page_url = page_url.replace("/v/","/api/source/") + + page_url = page.url + page_url = page_url.replace("/f/", "/v/") + page_url = page_url.replace("/v/", "/api/source/") data = httptools.downloadpage(page_url, post={}).json logger.debug(data) if "Video not found or" in data or "We are encoding this video" in data: @@ -26,9 +29,9 @@ def get_video_url(page_url, user="", password="", video_password=""): logger.debug("(page_url='%s')" % page_url) video_urls = [] for file in data['data']: - media_url = file['file'] - label = file['label'] - extension = file['type'] - video_urls.append([ extension + ' ' + label + ' [Fembed]', media_url]) + media_url = file['file'] + label = file['label'] + extension = file['type'] + video_urls.append([ extension + ' ' + label + ' [Fembed]', media_url]) video_urls.sort(key=lambda x: int(x[0].split()[1].replace('p',''))) return video_urls diff --git a/servers/hxfile.json b/servers/hxfile.json new file mode 100644 index 00000000..e5707946 --- /dev/null +++ b/servers/hxfile.json @@ -0,0 +1,42 @@ +{ + "active": true, + "find_videos": { + "ignore_urls": [], + "patterns": [ + { + "pattern": "https?://hxfile.co/(?!api)(?:embed-)?([A-z0-9]+)", + "url": "https://hxfile.co/embed-\\1.html" + } + ] + }, + "free": true, + "id": "hxfile", + "name": "HxFile", + "settings": [ + { + "default": false, + "enabled": true, + "id": "black_list", + "label": "@70708", + "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": "hxfile.png" +} \ No newline at end of file diff --git a/servers/hxfile.py b/servers/hxfile.py new file mode 100644 index 00000000..487463c8 --- /dev/null +++ b/servers/hxfile.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from core import httptools, scrapertools, servertools, support +from platformcode import logger, config +from lib import jsunpack + + +def test_video_exists(page_url): + logger.debug("(page_url='%s')" % page_url) + global data + data = httptools.downloadpage(page_url).data + if "Can't create video code" in data: + return False, config.get_localized_string(70292) % 'HxFile' + return True, "" + + +def get_video_url(page_url, premium=False, user="", password="", video_password=""): + logger.debug("url=" + page_url) + global data + video_urls = [] + packed = scrapertools.find_single_match(data, r'(eval\s?\(function\(p,a,c,k,e,d\).*?\n)') + data = jsunpack.unpack(packed) + video_urls.extend(support.get_jwplayer_mediaurl(data, 'HxFile')) + + return video_urls diff --git a/servers/mixdrop.json b/servers/mixdrop.json index bfa1908d..1141cc68 100644 --- a/servers/mixdrop.json +++ b/servers/mixdrop.json @@ -6,6 +6,10 @@ { "pattern": "mixdrop[s]?.[^/]+/(?:f|e)/([a-z0-9]+)", "url": "https://mixdrop.co/e/\\1" + }, + { + "pattern": "(mixdrop[s]?.[^/]+/player\\.php\\?id=[a-z0-9-]+)", + "url": "https://\\1" } ] }, diff --git a/servers/playtube.json b/servers/playtube.json new file mode 100644 index 00000000..c15809d4 --- /dev/null +++ b/servers/playtube.json @@ -0,0 +1,43 @@ +{ + "active": true, + "find_videos": { + "ignore_urls": [], + "patterns": [ + { + "pattern": "playtube.ws/(?:embed-|)(\\w+)", + "url": "https://playtube.ws/embed-\\1.html" + } + + ] + }, + "free": true, + "id": "playtube", + "name": "PlayTube", + "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": "playtube.png" +} \ No newline at end of file diff --git a/servers/playtube.py b/servers/playtube.py new file mode 100644 index 00000000..c9df8e0f --- /dev/null +++ b/servers/playtube.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# -------------------------------------------------------- +# Conector playtube By Alfa development Group +# -------------------------------------------------------- +import re +import codecs +from core import httptools +from core import scrapertools +from lib import jsunpack +from platformcode import logger + + +def test_video_exists(page_url): + logger.info("(page_url='%s')" % page_url) + global data + data = httptools.downloadpage(page_url) + if data.code == 404 or "File is no longer available" in data.data: + return False, config.get_localized_string(70449) % 'PlayTube' + return True, "" + + +def get_video_url(page_url, premium=False, user="", password="", video_password=""): + logger.info("url=" + page_url) + video_urls = [] + pack = scrapertools.find_single_match(data.data, 'p,a,c,k,e,d.*?</script>') + unpacked = jsunpack.unpack(pack) + url = scrapertools.find_single_match(unpacked, 'file:"([^"]+)') + "|referer=%s" %(page_url) + video_urls.append(['m3u8 [PlayTube]', url] ) + return video_urls \ No newline at end of file diff --git a/servers/speedvideo.py b/servers/speedvideo.py index 97190426..1700160a 100644 --- a/servers/speedvideo.py +++ b/servers/speedvideo.py @@ -4,16 +4,19 @@ from core import httptools, scrapertools from platformcode import config, logger + def test_video_exists(page_url): logger.debug("(page_url='%s')" % page_url) data = httptools.downloadpage(page_url).data - if "File was deleted" in data or "Video is transfer on streaming server now." in data: + if "File was deleted" in data or "Video is transfer on streaming server now." in data \ + or 'Conversione video in corso' in data: return False, config.get_localized_string(70449) % "Speedvideo" return True, "" + def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.debug("url=" + page_url) video_urls = [] diff --git a/servers/vidmoly.json b/servers/vidmoly.json index e8d4d984..aba842f8 100644 --- a/servers/vidmoly.json +++ b/servers/vidmoly.json @@ -4,7 +4,7 @@ "ignore_urls": [], "patterns": [ { - "pattern": "https?://vidmoly.net/(?:embed-)?(\\w+)\\.html", + "pattern": "https?://vidmoly.(?:net|to)/(?:embed-)?(\\w+)\\.html", "url": "https://vidmoly.net/embed-\\1.html" }, { diff --git a/servers/youdbox.json b/servers/youdbox.json index aff46ba7..94ea49e3 100644 --- a/servers/youdbox.json +++ b/servers/youdbox.json @@ -4,8 +4,8 @@ "ignore_urls": [], "patterns": [ { - "pattern": "(https://youdbox.com/embed-[A-z0-9-]+.html)", - "url": "\\1" + "pattern": "https://youdbox.(?:com|net)/embed-([A-z0-9-]+.html)", + "url": "https://youdbox.net/embed-\\1" } ] }, @@ -37,5 +37,6 @@ "type": "list", "visible": false } - ] + ], + "thumbnail": "youdbox.png" } diff --git a/service.py b/service.py index 4c1c88a1..4ad50208 100644 --- a/service.py +++ b/service.py @@ -89,21 +89,18 @@ def update(path, p_dialog, i, t, serie, overwrite): # serie.infoLabels['playcount'] = serie.playcount insertados_total += insertados - except Exception as ex: + except: + import traceback logger.error("Error when saving the chapters of the series") - template = "An exception of type %s occured. Arguments:\n%r" - message = template % (type(ex).__name__, ex.args) - logger.error(message) + logger.error(traceback.format_exc()) - except Exception as ex: + except: + import traceback logger.error("Error in obtaining the episodes of: %s" % serie.show) - template = "An exception of type %s occured. Arguments:\n%r" - message = template % (type(ex).__name__, ex.args) - logger.error(message) + logger.error(traceback.format_exc()) else: logger.debug("Channel %s not active is not updated" % serie.channel) - # Synchronize the episodes seen from the Kodi video library with that of KoD try: if config.is_xbmc(): # If it's Kodi, we do it @@ -127,7 +124,7 @@ def check_for_update(overwrite=True): if config.get_setting("update", "videolibrary") != 0 or overwrite: config.set_setting("updatelibrary_last_check", hoy.strftime('%Y-%m-%d'), "videolibrary") - heading = config.get_localized_string(60389) + heading = config.get_localized_string(60601) p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), heading) p_dialog.update(0, '') show_list = [] @@ -286,22 +283,6 @@ def check_for_update(overwrite=True): trakt_tools.update_all() -def viewmodeMonitor(): - try: - currentModeName = xbmc.getInfoLabel('Container.Viewmode') - win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) - currentMode = int(win.getFocusId()) - if currentModeName and 'plugin.video.kod' in xbmc.getInfoLabel('Container.FolderPath') and currentMode < 1000 and currentMode >= 50: # inside addon and in itemlist view - content, Type = platformtools.getCurrentView() - if content: - defaultMode = int(config.get_setting('view_mode_%s' % content).split(',')[-1]) - if currentMode != defaultMode: - logger.debug('viewmode changed: ' + currentModeName + '-' + str(currentMode) + ' - content: ' + content) - config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode)) - except: - logger.error(traceback.print_exc()) - - def updaterCheck(): # updater check updated, needsReload = updater.check(background=True) @@ -441,7 +422,7 @@ class AddonMonitor(xbmc.Monitor): logger.debug('scheduled videolibrary at ' + str(self.update_hour).zfill(2) + ':00') def scheduleScreenOnJobs(self): - schedule.every().second.do(viewmodeMonitor).tag('screenOn') + schedule.every().second.do(platformtools.viewmodeMonitor).tag('screenOn') schedule.every().second.do(torrent.elementum_monitor).tag('screenOn') def onDPMSActivated(self): diff --git a/specials/globalsearch.py b/specials/globalsearch.py index bef7f1c1..fce4723b 100644 --- a/specials/globalsearch.py +++ b/specials/globalsearch.py @@ -161,7 +161,7 @@ class SearchWindow(xbmcgui.WindowXML): tmdb_info = tmdb.discovery(self.item, dict_=self.item.discovery) results = tmdb_info.results.get('cast',[]) else: - tmdb_info = tmdb.Tmdb(texto_buscado=self.item.text, tipo=self.item.mode.replace('show', '')) + tmdb_info = tmdb.Tmdb(searched_text=self.item.text, search_type=self.item.mode.replace('show', '')) results = tmdb_info.results for result in results: diff --git a/specials/search.py b/specials/search.py index aa83cc6c..e420d47d 100644 --- a/specials/search.py +++ b/specials/search.py @@ -23,13 +23,9 @@ from channelselector import get_thumb from platformcode import logger, config, platformtools, unify from core.support import typo, thumb import xbmcgui - -import gc - import xbmc from threading import Thread from core.support import dbg -gc.disable() info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json def_lang = info_language[config.get_setting("info_language", "videolibrary")] @@ -38,7 +34,8 @@ def_lang = info_language[config.get_setting("info_language", "videolibrary")] def mainlist(item): logger.debug() - if config.get_setting('new_search'): + if platformtools.get_window() not in ('WINDOW_SETTINGS_MENU', 'WINDOW_SETTINGS_INTERFACE', 'WINDOW_SKIN_SETTINGS')\ + and xbmc.getInfoLabel('System.CurrentWindow') in ('Home', '') and config.get_setting('new_search'): itemlist = [Item(channel='globalsearch', title=config.get_localized_string(70276), action='Search', mode='all', thumbnail=get_thumb("search.png"), folder=False), Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30122), action='Search', mode='movie', thumbnail=get_thumb("search_movie.png"),folder=False), Item(channel='globalsearch', title=config.get_localized_string(70741) % config.get_localized_string(30123), action='Search', mode='tvshow', thumbnail=get_thumb("search_tvshow.png"), folder=False), @@ -135,7 +132,7 @@ def new_search(item): return actor_list(item) if item.mode != 'all': - tmdb_info = tmdb.Tmdb(texto_buscado=searched_text, tipo=item.mode.replace('show', '')) + tmdb_info = tmdb.Tmdb(searched_text=searched_text, search_type=item.mode.replace('show', '')) results = tmdb_info.results for result in results: result = tmdb_info.get_infoLabels(result, origen=result) @@ -563,7 +560,7 @@ def genres_menu(item): itemlist = [] mode = item.mode.replace('show', '') - genres = tmdb.get_genres(mode) + genres = tmdb.get_dic_genres(mode) for key, value in list(genres[mode].items()): discovery = {'url': 'discover/%s' % mode, 'with_genres': key, 'language': def_lang, 'page': '1'} diff --git a/specials/trailertools.py b/specials/trailertools.py index c253f217..0790788e 100644 --- a/specials/trailertools.py +++ b/specials/trailertools.py @@ -6,6 +6,7 @@ from __future__ import division # from builtins import str +import random import sys from channelselector import get_thumb @@ -165,9 +166,9 @@ def tmdb_trailers(item, dialog, tipo="movie"): itemlist = [] tmdb_search = None if item.infoLabels['tmdb_id']: - tmdb_search = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], tipo=tipo, idioma_busqueda=def_lang) + tmdb_search = Tmdb(id_Tmdb=item.infoLabels['tmdb_id'], tipo=tipo, search_language=def_lang) elif item.infoLabels['year']: - tmdb_search = Tmdb(texto_buscado=item.contentTitle, tipo=tipo, year=item.infoLabels['year']) + tmdb_search = Tmdb(searched_text=item.contentTitle, tipo=tipo, year=item.infoLabels['year']) if tmdb_search: found = False @@ -199,6 +200,8 @@ def youtube_search(item): else: title = urllib.quote(title) title = title.replace("%20", "+") + httptools.set_cookies({'domain': 'youtube.com', 'name': 'CONSENT', + 'value': 'YES+cb.20210328-17-p0.en+FX+' + str(random.randint(100, 999))}) data = httptools.downloadpage("https://www.youtube.com/results?sp=EgIQAQ%253D%253D&search_query=" + title).data patron = r'thumbnails":\[\{"url":"(https://i.ytimg.com/vi[^"]+).*?' patron += r'text":"([^"]+).*?' diff --git a/specials/tvmoviedb.json b/specials/tvmoviedb.json index 9c9115e1..81c365c6 100644 --- a/specials/tvmoviedb.json +++ b/specials/tvmoviedb.json @@ -3,7 +3,7 @@ "name": "TvMovieDB", "active": false, "language": ["*"], - "thumbnail": "http://i.imgur.com/HA7fvgD.png", + "thumbnail": "https://i.imgur.com/5CETVTV.jpg", "categories": [ "movie", "tvshow", @@ -92,4 +92,4 @@ "visible": true } ] -} \ No newline at end of file +} diff --git a/specials/tvmoviedb.py b/specials/tvmoviedb.py index a19b2a1f..8861e2fe 100644 --- a/specials/tvmoviedb.py +++ b/specials/tvmoviedb.py @@ -242,7 +242,7 @@ def mal(item): itemlist.append(item.clone(title=config.get_localized_string(70058), url="https://myanimelist.net/topanime.php?type=tv&limit=0", action="top_mal", contentType="tvshow", args="tv")) itemlist.append(item.clone(title=config.get_localized_string(70059), url="https://myanimelist.net/topanime.php?type=movie&limit=0", action="top_mal", contentType="movie", args="movie")) - itemlist.append(item.clone(title=config.get_localized_string(70061), url="https://myanimelist.net/topanime.php?type=ova&limit=0", action="top_mal", contentType="tvshow", args="tv", tipo="ova")) + itemlist.append(item.clone(title=config.get_localized_string(70061), url="https://myanimelist.net/topanime.php?type=ova&limit=0", action="top_mal", contentType="tvshow", args="tv", Type="ova")) itemlist.append(item.clone(title=config.get_localized_string(70028), url="https://myanimelist.net/topanime.php?type=bypopularity&limit=0", action="top_mal")) itemlist.append(item.clone(title=config.get_localized_string(70060), url="https://myanimelist.net/topanime.php?type=upcoming&limit=0", action="top_mal")) itemlist.append(item.clone(title=config.get_localized_string(70062), url="", action="indices_mal")) @@ -267,15 +267,15 @@ def list_tmdb(item): # List of actors if 'nm' in item.infoLabels['imdb_id']: try: - ob_tmdb = Tmdb(discover=item.search, tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=item.search, search_type=item.args, search_language=langt) id_cast = ob_tmdb.result["person_results"][0]["id"] if item.contentType == "movie": item.search = {'url': 'discover/movie', 'with_cast': id_cast, 'page': item.pagina, 'sort_by': 'primary_release_date.desc', 'language': langt} else:item.search = {'url': 'person/%s/tv_credits' % id_cast, 'language': langt} - ob_tmdb = Tmdb(discover=item.search, tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=item.search, search_type=item.args, search_language=langt) except: pass else: - ob_tmdb = Tmdb(discover=item.search, tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=item.search, search_type=item.args, search_language=langt) # Sagas and collections if "collection" in item.search["url"]: @@ -307,8 +307,8 @@ def list_tmdb(item): new_item.infoLabels = ob_tmdb.get_infoLabels(new_item.infoLabels, origen=ob_tmdb.results[i]) # If there is no synopsis in the chosen language, search in the alternative if not new_item.infoLabels["plot"] and not 'person' in item.search["url"]: - ob_tmdb2 = Tmdb(id_Tmdb=new_item.infoLabels["tmdb_id"], tipo=item.args, idioma_busqueda=langt_alt) - new_item.infoLabels["plot"] = ob_tmdb2.get_sinopsis() + ob_tmdb2 = Tmdb(id_Tmdb=new_item.infoLabels["tmdb_id"], search_type=item.args, search_language=langt_alt) + new_item.infoLabels["plot"] = ob_tmdb2.get_plot() if new_item.infoLabels['thumbnail']: new_item.thumbnail = new_item.infoLabels['thumbnail'] elif new_item.infoLabels['profile_path']: @@ -375,10 +375,10 @@ def details(item): pics = match(data, patron=r'showAllVidsAndPics.*?href=".*?(tt\d+)').match if pics: images["imdb"] = {'url': 'http://www.imdb.com/_json/title/%s/mediaviewer' % pics} - ob_tmdb = Tmdb(external_id=item.infoLabels["imdb_id"], external_source="imdb_id", tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(external_id=item.infoLabels["imdb_id"], external_source="imdb_id", search_type=item.args, search_language=langt) item.infoLabels["tmdb_id"] = ob_tmdb.get_id() - ob_tmdb = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], search_type=item.args, search_language=langt) try: item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels) @@ -420,7 +420,7 @@ def details(item): itemlist.append(item.clone(channel='search', action="search", search_text=item.infoLabels['originaltitle'], title=config.get_localized_string(70070) % item.infoLabels['originaltitle'], mode=item.contentType)) # if langt != "es" and langt != "en" and item.infoLabels["tmdb_id"]: - # tmdb_lang = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo=item.args, idioma_busqueda=def_lang) + # tmdb_lang = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], search_type=item.args, search_language=def_lang) # if tmdb_lang.result.get("title") and tmdb_lang.result["title"] != item.contentTitle and tmdb_lang.result["title"] != item.infoLabels['originaltitle']: # tmdb_lang = tmdb_lang.result["title"] # itemlist.append(item.clone(channel='search', action="search", title=config.get_localized_string(70066) % tmdb_lang, contentTitle=tmdb_lang, mode=item.contentType)) @@ -500,7 +500,7 @@ def distribution(item): itemlist = [] item.args=item.contentType.replace('tvshow','tv') item.search = {'url': '%s/%s/credits' % (item.args, item.infoLabels['tmdb_id'])} - ob_tmdb = Tmdb(discover=item.search, tipo=item.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=item.search, search_type=item.args, search_language=langt) try: cast = ob_tmdb.result["cast"] @@ -545,7 +545,7 @@ def distribution(item): def info_seasons(item): # Season and episode info itemlist = [] - ob_tmdb = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo="tv", idioma_busqueda=langt) + ob_tmdb = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], search_type="tv", search_language=langt) logger.info(item.infoLabels) for temp in range(int(item.infoLabels["number_of_seasons"]), 0, -1): @@ -1217,19 +1217,19 @@ def indices_imdb(item): # item_tmdb = item.clone() # if item.contentType == "movie": -# ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, year=item_tmdb.infoLabels['year'], tipo=item_tmdb.args, -# idioma_busqueda=langt) +# ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, year=item_tmdb.infoLabels['year'], search_type=item_tmdb.args, +# search_language=langt) # if not ob_tmdb.result: # ob_tmdb = Tmdb(text_buscado=item_tmdb.infoLabels['originaltitle'], year=item_tmdb.infoLabels['year'], -# tipo=item_tmdb.args, idioma_busqueda=langt) +# search_type=item_tmdb.args, search_language=langt) # else: -# ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, tipo=item_tmdb.args, idioma_busqueda=langt) +# ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, search_type=item_tmdb.args, search_language=langt) # if not ob_tmdb.result: -# ob_tmdb = Tmdb(text_buscado=item_tmdb.infoLabels['tvshowtitle'], tipo=item_tmdb.args, -# idioma_busqueda=langt) +# ob_tmdb = Tmdb(text_buscado=item_tmdb.infoLabels['tvshowtitle'], search_type=item_tmdb.args, +# search_language=langt) # if ob_tmdb.result: -# ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), tipo=item_tmdb.args, idioma_busqueda=langt) +# ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), search_type=item_tmdb.args, search_language=langt) # item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels) # # If there is no synopsis in the chosen language, search in the alternative @@ -1289,7 +1289,7 @@ def indices_imdb(item): # title=config.get_localized_string(70070) % item.infoLabels['originaltitle'])) # if langt != "es" and langt != "en" and item.infoLabels["tmdb_id"]: -# tmdb_lang = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], tipo=item.args, idioma_busqueda=def_lang) +# tmdb_lang = Tmdb(id_Tmdb=item.infoLabels["tmdb_id"], search_type=item.args, search_language=def_lang) # if tmdb_lang.result.get("title") and tmdb_lang.result["title"] != item.contentTitle: # tmdb_lang = tmdb_lang.result["title"] # itemlist.append(item.clone(action="searching", title=config.get_localized_string(70066) % tmdb_lang, @@ -1778,11 +1778,11 @@ def imagenes(item): for key, value in item.images.items(): if key == "tmdb" and "Tmdb" in item.title: if item.folder: - for tipo, child in value.iteritems(): + for Type, child in value.iteritems(): for i, imagen in enumerate(child): thumb = 'https://image.tmdb.org/t/p/w500' + imagen["file_path"] fanart = 'https://image.tmdb.org/t/p/original' + imagen["file_path"] - title = " %s %s [%sx%s]" % (tipo.capitalize(), i + 1, imagen["width"], imagen["height"]) + title = " %s %s [%sx%s]" % (Type.capitalize(), i + 1, imagen["width"], imagen["height"]) itemlist.append(Item(channel=item.channel, action="", thumbnail=thumb, fanart=fanart, title=title, infoLabels=item.infoLabels)) else: @@ -1790,11 +1790,11 @@ def imagenes(item): elif key == "fanart.tv": if item.folder: - for tipo, child in value.iteritems(): + for Type, child in value.iteritems(): for i, imagen in enumerate(child): thumb = imagen["url"].replace("/fanart/", "/preview/") fanart = imagen["url"] - title = " %s %s [%s]" % (tipo.capitalize(), i + 1, imagen["lang"]) + title = " %s %s [%s]" % (Type.capitalize(), i + 1, imagen["lang"]) itemlist.append(Item(channel=item.channel, action="", thumbnail=thumb, fanart=fanart, title=title, infoLabels=item.infoLabels)) else: @@ -1838,7 +1838,7 @@ def fanartv(item): id_search = item.infoLabels['tmdb_id'] if item.contentType == "tvshow" and id_search: search = {'url': 'tv/%s/external_ids' % item.infoLabels['tmdb_id'], 'language': langt} - ob_tmdb = Tmdb(discover=search, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=search, search_language=langt) id_search = ob_tmdb.result.get("tvdb_id") resultado = False @@ -1869,27 +1869,27 @@ def menu_trakt(item): # Menu with trakt account actions (views, watchlist, collection) itemlist = [] token_auth = config.get_setting("token_trakt", "trakt") - tipo = item.args.replace("tv", "show") + "s" + Type = item.args.replace("tv", "show") + "s" title = item.contentType.replace("movie", config.get_localized_string(70283)).replace("tvshow", config.get_localized_string(30123)) try: - result = acciones_trakt(item.clone(url="sync/watched/%s" % tipo)) - post = {tipo: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} + result = acciones_trakt(item.clone(url="sync/watched/%s" % Type)) + post = {Type: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} if '"tmdb":%s' % item.infoLabels["tmdb_id"] in result: itemlist.append(item.clone(title=config.get_localized_string(70341) % title, action="acciones_trakt", url="sync/history/remove", post=post)) else: itemlist.append(item.clone(title=config.get_localized_string(70342) % title, action="acciones_trakt", url="sync/history", post=post)) except: pass try: - result = acciones_trakt(item.clone(url="sync/watchlist/%s" % tipo)) - post = {tipo: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} + result = acciones_trakt(item.clone(url="sync/watchlist/%s" % Type)) + post = {Type: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} if '"tmdb":%s' % item.infoLabels["tmdb_id"] in result: itemlist.append(item.clone(title=config.get_localized_string(70343) % title, action="acciones_trakt", url="sync/watchlist/remove", post=post)) else: itemlist.append(item.clone(title=config.get_localized_string(70344) % title, action="acciones_trakt", url="sync/watchlist", post=post)) except: pass try: - result = acciones_trakt(item.clone(url="sync/collection/%s" % tipo)) - post = {tipo: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} + result = acciones_trakt(item.clone(url="sync/collection/%s" % Type)) + post = {Type: [{"ids": {"tmdb": item.infoLabels["tmdb_id"]}}]} if '"tmdb":%s' % item.infoLabels["tmdb_id"] in result: itemlist.append(item.clone(title=config.get_localized_string(70345) % title, action="acciones_trakt", url="sync/collection/remove", post=post)) else: itemlist.append(item.clone(title=config.get_localized_string(70346) % title, action="acciones_trakt", url="sync/collection", post=post)) except: @@ -2104,7 +2104,7 @@ def details_mal(item): title_mal = item.contentTitle if not item.args: args = match(data, patron=r'Type:</span>.*?>([^<]+)</a>').match.lower() - item.tipo = args + item.type = args if args == "movie" or args == "special": item.args = "movie" item.contentType = "movie" @@ -2124,25 +2124,25 @@ def details_mal(item): item_tmdb = item.clone() if item.contentType == "movie": - ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, year=item_tmdb.infoLabels['year'], tipo=item_tmdb.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, year=item_tmdb.infoLabels['year'], search_type=item_tmdb.args, search_language=langt) if not ob_tmdb.result and eng_title: - ob_tmdb = Tmdb(text_buscado=eng_title, year=item_tmdb.infoLabels['year'], tipo=item_tmdb.args, idioma_busqueda=langt) - if not ob_tmdb.result and ("Special (" in item.title or item.tipo == "special"): + ob_tmdb = Tmdb(text_buscado=eng_title, year=item_tmdb.infoLabels['year'], search_type=item_tmdb.args, search_language=langt) + if not ob_tmdb.result and ("Special (" in item.title or item.type == "special"): item_tmdb.args = "tv" search = {'url': 'search/tv', 'language': langt, 'query': item_tmdb.contentTitle, 'first_air_date': item_tmdb.infoLabels["year"]} - ob_tmdb = Tmdb(discover=search, tipo=item_tmdb.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=search, search_type=item_tmdb.args, search_language=langt) else: search = {'url': 'search/tv', 'language': langt, 'query': eng_title, 'first_air_date': item_tmdb.infoLabels["year"]} - ob_tmdb = Tmdb(discover=search, tipo=item_tmdb.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(discover=search, search_type=item_tmdb.args, search_language=langt) if not ob_tmdb.result and eng_title: search['query'] = eng_title - ob_tmdb = Tmdb(discover=search, tipo=item_tmdb.args, idioma_busqueda=langt) - if not ob_tmdb.result and ("OVA (" in item.title or item.tipo == "ova"): + ob_tmdb = Tmdb(discover=search, search_type=item_tmdb.args, search_language=langt) + if not ob_tmdb.result and ("OVA (" in item.title or item.type == "ova"): item_tmdb.args = "movie" - ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, tipo=item_tmdb.args, idioma_busqueda=langt, year=item_tmdb.infoLabels['year']) + ob_tmdb = Tmdb(text_buscado=item_tmdb.contentTitle, search_type=item_tmdb.args, search_language=langt, year=item_tmdb.infoLabels['year']) if ob_tmdb.result: - ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), tipo=item_tmdb.args, idioma_busqueda=langt) + ob_tmdb = Tmdb(id_Tmdb=ob_tmdb.get_id(), search_type=item_tmdb.args, search_language=langt) item.infoLabels = ob_tmdb.get_infoLabels(item.infoLabels) # Myanimelist synopsis is concatenated with that of tmdb if any @@ -2389,10 +2389,10 @@ def season_mal(item): matches = match(block, patron=patron, debug=True).matches if matches: itemlist.append(Item(channel=item.channel, action="", title=head_title, )) - for url, scrapedtitle, episode, genres, thumb, plot, tipo, year, score in matches: + for url, scrapedtitle, episode, genres, thumb, plot, Type, year, score in matches: if ("Hentai" in genres or "Yaoi" in genres or "Yuri" in genres) and adult_mal: continue scrapedtitle = scrapedtitle.replace("(TV)", "").replace("(Movie)", "") - if tipo == "Movie": title = scrapedtitle + " (%s)" % year + if Type == "Movie": title = scrapedtitle + " (%s)" % year else: title = scrapedtitle + " %ss (%s)" % (episode, year) infoLabels = {} if score != "N/A": @@ -2403,23 +2403,23 @@ def season_mal(item): genres = match(genres, patron=r'title="([^"]+)"').matches infoLabels["genre"] = ", ".join(genres) - tipo = tipo.lower() - if tipo == "movie" or tipo == "special": + Type = Type.lower() + if Type == "movie" or Type == "special": args = "movie" contentType = "movie" else: args = "tv" contentType = "tvshow" thumb = thumb.replace("r/167x242/", "") + "l.jpg" - itemlist.append(Item(channel=item.channel, action="details_mal", url=url, title=title, thumbnail=thumb, infoLabels=infoLabels, args=args, tipo=tipo, contentTitle=scrapedtitle, contentType=contentType, fanart=default_fan)) + itemlist.append(Item(channel=item.channel, action="details_mal", url=url, title=title, thumbnail=thumb, infoLabels=infoLabels, args=args, Type=Type, contentTitle=scrapedtitle, contentType=contentType, fanart=default_fan)) else: patron = r'<a href="([^"]+)" class="link-title">([^<]+)</a>.*?<span>(\? ep|\d+ ep).*?<div class="genres-inner js-genre-inner">(.*?)</div>.*?<div class="image".*?src="([^"]+).*?<span class="preline">(.*?)</span>.*?<div class="info">\s*(.*?)\s*-.*?(\d{4}).*?title="Score">\s*(N/A|\d\.\d+)' matches = match(data, patron=patron).matches - for url, scrapedtitle, epis, scrapedgenres, thumbnail, plot, tipo, year, score in matches: + for url, scrapedtitle, epis, scrapedgenres, thumbnail, plot, Type, year, score in matches: if ("Hentai" in scrapedgenres or "Yaoi" in scrapedgenres or "Yuri" in scrapedgenres) and not adult_mal: continue scrapedtitle = scrapedtitle.replace("(TV)", "").replace("(Movie)", "") - if tipo == "Movie": + if Type == "Movie": title = scrapedtitle + " (%s)" % year else: title = scrapedtitle + " %ss (%s)" % (epis, year) @@ -2432,8 +2432,8 @@ def season_mal(item): genres = match(scrapedgenres, patron=r'title="([^"]+)"').matches infoLabels["genre"] = ", ".join(genres) - tipo = tipo.lower() - if tipo == "movie" or tipo == "special": + Type = Type.lower() + if Type == "movie" or Type == "special": args = "movie" contentType = "movie" else: @@ -2441,7 +2441,7 @@ def season_mal(item): contentType = "tvshow" thumbnail = thumbnail.replace(".webp", ".jpg") itemlist.append(Item(channel=item.channel, action="details_mal", url=url, title=title, - thumbnail=thumbnail, infoLabels=infoLabels, args=args, tipo=tipo, + thumbnail=thumbnail, infoLabels=infoLabels, args=args, Type=Type, contentTitle=scrapedtitle, contentType=contentType, fanart=default_fan)) next_page = match(data, patron=r'<a class="link current" href.*?href="([^"]+)"').match @@ -2552,12 +2552,12 @@ def searching_mal(item): data = match(item.url, headers=header_mal, cookies=False).data patron = r'<a class="hoverinfo_trigger" href="([^"]+)".*?(?:data-src|src)="([^"]+)".*?<div class="hoverinfo".*?href.*?><strong>([^<]+)<.*?<div class="pt4">(.*?)<.*?<td.*?>(.*?)</td>.*?<td.*?>(.*?)</td>.*?<td.*?>(.*?)</td>.*?<td.*?>(.*?)</td>' matches = match(data, patron=patron).matches - for url, thumb, title, plot, tipo, epis, rating, date in matches: + for url, thumb, title, plot, Type, epis, rating, date in matches: infolabels = {"mediatype": "tvshow"} contentType = "tvshow" args = "tv" title = title.strip() - tipo = tipo.strip() + Type = Type.strip() rating = rating.strip() epis = epis.strip() infolabels["plot"] = htmlclean(plot.strip()) @@ -2578,20 +2578,20 @@ def searching_mal(item): import traceback logger.error(traceback.format_exc()) - if tipo == "Movie" or tipo == "OVA": + if Type == "Movie" or Type == "OVA": infolabels["mediatype"] = "movie" contentType = "movie" args = "movie" show = "" - if epis and tipo != "Movie": + if epis and Type != "Movie": title += " %s eps" % epis if rating != "0.00" and rating != "N/A": infolabels["rating"] = float(rating) title += " %s" % (rating) itemlist.append(Item(channel=item.channel, title=title, action="details_mal", url=url, show=show, thumbnail=thumb, infoLabels=infolabels, contentTitle=contentitle, - contentType=contentType, tipo=tipo.lower(), args=args)) + contentType=contentType, Type=Type.lower(), args=args)) if not "&show=" in item.url: next_page = item.url + "&show=50" @@ -2713,13 +2713,13 @@ def callback_mal(item, values): genero_ids = "&".join(genero_ids) query = values["keyword"].replace(" ", "%20") - tipo = item.valores["tipo"][values["tipo"]] + Type = item.valores["tipo"][values["tipo"]] valoracion = item.valores["valoracion"][values["valoracion"]] estado = item.valores["estado"][values["estado"]] item.url = "https://myanimelist.net/anime.php?q=%s&type=%s&score=%s&status=%s" \ "&p=0&r=0&sm=0&sd=0&sy=0&em=0&ed=0&ey=0&c[0]=a&c[1]=b&c[2]=c&c[3]=d&c[4]=f&gx=0" \ - % (query, tipo, valoracion, estado) + % (query, Type, valoracion, estado) if genero_ids: item.url += "&" + genero_ids @@ -2851,14 +2851,14 @@ def items_mal(item): title = title.replace("] (TV)", "]") elif title.count("(Movie)") == 2: title = title.replace("] (Movie)", "]") - tipo = "tvshow" + Type = "tvshow" args = "tv" if "Movie" in d["anime_media_type_string"]: - tipo = "movie" + Type = "movie" args = "movie" itemlist.append(Item(channel=item.channel, action="details_mal", url=url, title=title, thumbnail=thumbnail, - contentTitle=contentTitle, contentType=tipo, args=args, login=True)) + contentTitle=contentTitle, contentType=Type, args=args, login=True)) if itemlist: itemlist.insert(0, Item(channel=item.channel, action="", title=config.get_localized_string(70387))) diff --git a/updatetvshow.py b/updatetvshow.py deleted file mode 100644 index 159009a3..00000000 --- a/updatetvshow.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -import xbmc, sys, xbmcgui, os, xbmcvfs, traceback -from platformcode import config, logger - -librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib')) -sys.path.insert(0, librerias) - -from core.item import Item -from lib.sambatools import libsmb as samba -from core import scrapertools - - -def exists(path, silent=False, vfs=True): - path = xbmc.translatePath(path) - try: - if vfs: - result = bool(xbmcvfs.exists(path)) - if not result and not path.endswith('/') and not path.endswith('\\'): - result = bool(xbmcvfs.exists(join(path, ' ').rstrip())) - return result - elif path.lower().startswith("smb://"): - return samba.exists(path) - else: - return os.path.exists(path) - except: - logger.error("ERROR when checking the path: %s" % path) - if not silent: - logger.error(traceback.format_exc()) - return False - -def join(*paths): - list_path = [] - if paths[0].startswith("/"): - list_path.append("") - for path in paths: - if path: - list_path += path.replace("\\", "/").strip("/").split("/") - - if scrapertools.find_single_match(paths[0], r'(^\w+:\/\/)'): - return str("/".join(list_path)) - else: - return str(os.sep.join(list_path)) - - -def search_paths(Id): - records = execute_sql('SELECT idPath FROM tvshowlinkpath WHERE idShow LIKE "%s"' % Id) - if len(records) >= 1: - for record in records: - path_records = execute_sql('SELECT strPath FROM path WHERE idPath LIKE "%s"' % record[0]) - for path in path_records: - if config.get_setting('videolibrarypath') in path[0] and exists(join(path[0], 'tvshow.nfo')): - return path[0] - return '' - - -def execute_sql(sql): - logger.debug() - file_db = "" - records = None - - # We look for the archive of the video database according to the version of kodi - video_db = config.get_platform(True)['video_db'] - if video_db: - file_db = os.path.join(xbmc.translatePath("special://userdata/Database"), video_db) - - # alternative method to locate the database - if not file_db or not os.path.exists(file_db): - file_db = "" - for f in os.path.listdir(xbmc.translatePath("special://userdata/Database")): - path_f = os.path.join(xbmc.translatePath("special://userdata/Database"), f) - - if os.path.pathoos.pathols.isfile(path_f) and f.lower().startswith('myvideos') and f.lower().endswith('.db'): - file_db = path_f - break - - if file_db: - logger.debug("DB file: %s" % file_db) - conn = None - try: - import sqlite3 - conn = sqlite3.connect(file_db) - cursor = conn.cursor() - - logger.debug("Running sql: %s" % sql) - cursor.execute(sql) - conn.commit() - - records = cursor.fetchall() - if sql.lower().startswith("select"): - if len(records) == 1 and records[0][0] is None: - records = [] - - conn.close() - logger.debug("Query executed. Records: %s" % len(records)) - - except: - logger.error("Error executing sql query") - if conn: - conn.close() - - else: - logger.debug("Database not found") - - return records - -if __name__ == '__main__': - path = search_paths(sys.listitem.getVideoInfoTag().getDbId()) - if path: - item = Item(action="update_tvshow", channel="videolibrary", path=path) - # Why? I think it is not necessary, just commented - # item.tourl() - xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")") - else: - dialog = xbmcgui.Dialog() - title = sys.listitem.getVideoInfoTag().getTitle() - if dialog.yesno(title, config.get_localized_string(70817) % title, nolabel=config.get_localized_string(70170), yeslabel=config.get_localized_string(30022)): - item = Item(action="new_search", channel="search", mode="tvshow", search_text=sys.listitem.getVideoInfoTag().getTitle()) - xbmc.executebuiltin("ActivateWindow(10025,plugin://plugin.video.kod/?" + item.tourl() + ")")