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
This commit is contained in:
18
addon.xml
18
addon.xml
@@ -1,4 +1,4 @@
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.6.3" provider-name="KoD Team">
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.7" provider-name="KoD Team">
|
||||
<requires>
|
||||
<!-- <import addon="script.module.libtorrent" optional="true"/> -->
|
||||
<import addon="metadata.themoviedb.org"/>
|
||||
@@ -11,14 +11,10 @@
|
||||
</extension>
|
||||
<extension point="kodi.context.item">
|
||||
<menu id="kodi.core.main">
|
||||
<item library="updatetvshow.py">
|
||||
<label>70269</label>
|
||||
<visible>String.IsEqual(ListItem.dbtype,tvshow)</visible>
|
||||
<item library="contextmenu.py">
|
||||
<label>90001</label>
|
||||
<visible>!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) ]</visible>
|
||||
</item>
|
||||
<!-- <item library="externalsearch.py">-->
|
||||
<!-- <label>90001</label>-->
|
||||
<!-- <visible>!String.StartsWith(ListItem.FileNameAndPath, plugin://plugin.video.kod/) + [String.IsEqual(ListItem.dbtype,tvshow) | String.IsEqual(ListItem.dbtype,movie)]</visible>-->
|
||||
<!-- </item>-->
|
||||
</menu>
|
||||
</extension>
|
||||
<extension point="xbmc.addon.metadata">
|
||||
@@ -31,8 +27,10 @@
|
||||
<screenshot>resources/media/screenshot-2.png</screenshot>
|
||||
<screenshot>resources/media/screenshot-3.png</screenshot>
|
||||
</assets>
|
||||
<news>- Corretto blocco nella ricerca globale
|
||||
- migliorie e fix vari ai canali e al core</news>
|
||||
<news>- 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)
|
||||
</news>
|
||||
<description lang="it">Naviga velocemente sul web e guarda i contenuti presenti</description>
|
||||
<disclaimer>[COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR]
|
||||
[COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR]</disclaimer>
|
||||
|
||||
@@ -1,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",
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -29,6 +29,7 @@ def mainlist(item):
|
||||
def menu(item):
|
||||
item.contentType = ''
|
||||
action = 'peliculas'
|
||||
|
||||
|
||||
patronBlock = r'<div class="filter-header"><b>%s</b>(?P<block>.*?)<div class="filter-box">' % item.args
|
||||
patronMenu = r'<a class="[^"]+" data-state="[^"]+" (?P<other>[^>]+)>[^>]+></i>[^>]+></i>[^>]+></i>(?P<title>[^>]+)</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)
|
||||
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "ilgeniodellostreaming_cam",
|
||||
"name": "IlGenioDelloStreaming CAM",
|
||||
"active": true,
|
||||
"active": false,
|
||||
"language": ["ita"],
|
||||
"thumbnail": "ilgeniodellostreaming.png",
|
||||
"banner": "ilgeniodellostreaming.png",
|
||||
|
||||
11
channels/tapmovie.json
Normal file
11
channels/tapmovie.json
Normal file
@@ -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": []
|
||||
}
|
||||
102
channels/tapmovie.py
Normal file
102
channels/tapmovie.py
Normal file
@@ -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)
|
||||
63
contextmenu.py
Normal file
63
contextmenu.py
Normal file
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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':
|
||||
|
||||
747
core/tmdb.py
747
core/tmdb.py
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
|
||||
5
platformcode/contextmenu/contextmenu.json
Normal file
5
platformcode/contextmenu/contextmenu.json
Normal file
@@ -0,0 +1,5 @@
|
||||
[
|
||||
"platformcode.contextmenu.search",
|
||||
"platformcode.contextmenu.tvshow_options",
|
||||
"platformcode.contextmenu.trailer"
|
||||
]
|
||||
127
platformcode/contextmenu/search.py
Normal file
127
platformcode/contextmenu/search.py
Normal file
@@ -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 + ")")
|
||||
|
||||
|
||||
|
||||
|
||||
23
platformcode/contextmenu/trailer.py
Normal file
23
platformcode/contextmenu/trailer.py
Normal file
@@ -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() + ")")
|
||||
214
platformcode/contextmenu/tvshow_options.py
Normal file
214
platformcode/contextmenu/tvshow_options.py
Normal file
@@ -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() + ")")
|
||||
@@ -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):
|
||||
|
||||
@@ -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]:
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
42
servers/hxfile.json
Normal file
42
servers/hxfile.json
Normal file
@@ -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"
|
||||
}
|
||||
25
servers/hxfile.py
Normal file
25
servers/hxfile.py
Normal file
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
43
servers/playtube.json
Normal file
43
servers/playtube.json
Normal file
@@ -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"
|
||||
}
|
||||
29
servers/playtube.py
Normal file
29
servers/playtube.py
Normal file
@@ -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
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
35
service.py
35
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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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":"([^"]+).*?'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)))
|
||||
|
||||
118
updatetvshow.py
118
updatetvshow.py
@@ -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() + ")")
|
||||
Reference in New Issue
Block a user