KoD 1.6.2

- Migliorata funzione cerca trailer\n- Episodio successivo: è ora disponibile la modalità playlist (puoi usare il tasto riproduci successivo di kodi)\n- aggiunto www.accuradio.com\n- migliorie varie\n
This commit is contained in:
mac12m99
2021-04-07 20:16:21 +02:00
parent 8441b1e28a
commit b2bd3e61d1
30 changed files with 457 additions and 391 deletions
+8 -6
View File
@@ -1,4 +1,4 @@
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.6.1" provider-name="KoD Team"> <addon id="plugin.video.kod" name="Kodi on Demand" version="1.6.2" provider-name="KoD Team">
<requires> <requires>
<!-- <import addon="script.module.libtorrent" optional="true"/> --> <!-- <import addon="script.module.libtorrent" optional="true"/> -->
<import addon="metadata.themoviedb.org"/> <import addon="metadata.themoviedb.org"/>
@@ -23,12 +23,14 @@
<assets> <assets>
<icon>resources/media/logo.png</icon> <icon>resources/media/logo.png</icon>
<fanart>resources/media/fanart.jpg</fanart> <fanart>resources/media/fanart.jpg</fanart>
<screenshot>resources/media/themes/ss/1.png</screenshot> <screenshot>resources/media/screenshot-1.png</screenshot>
<screenshot>resources/media/themes/ss/2.png</screenshot> <screenshot>resources/media/screenshot-2.png</screenshot>
<screenshot>resources/media/themes/ss/3.png</screenshot> <screenshot>resources/media/screenshot-3.png</screenshot>
</assets> </assets>
<news>-Migliorata l'efficacia del riconoscimento dei contenuti in ricerca film/serie <news>- Migliorata funzione &quot;cerca trailer&quot;
- corretti alcuni bug e fatti alcuni fix per i soliti cambi di struttura</news> - Episodio successivo: è ora disponibile la modalità playlist (puoi usare il tasto riproduci successivo di kodi)
- aggiunto www.accuradio.com
- migliorie varie</news>
<description lang="it">Naviga velocemente sul web e guarda i contenuti presenti</description> <description lang="it">Naviga velocemente sul web e guarda i contenuti presenti</description>
<disclaimer>[COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR] <disclaimer>[COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR]
[COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR]</disclaimer> [COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR]</disclaimer>
+9 -9
View File
@@ -14,7 +14,7 @@
"casacinema": "https://www.casacinema.page", "casacinema": "https://www.casacinema.page",
"cb01anime": "https://www.cineblog01.red", "cb01anime": "https://www.cineblog01.red",
"cineblog01": "https://cb01.uno", "cineblog01": "https://cb01.uno",
"cinemalibero": "https://cinemalibero.website", "cinemalibero": "https://cinemalibero.pink",
"cinetecadibologna": "http://cinestore.cinetecadibologna.it", "cinetecadibologna": "http://cinestore.cinetecadibologna.it",
"discoveryplus": "https://www.discoveryplus.com", "discoveryplus": "https://www.discoveryplus.com",
"dreamsub": "https://dreamsub.stream", "dreamsub": "https://dreamsub.stream",
@@ -22,24 +22,24 @@
"eurostreaming": "https://eurostreaming.team", "eurostreaming": "https://eurostreaming.team",
"filmgratis": "https://www.filmaltadefinizione.me", "filmgratis": "https://www.filmaltadefinizione.me",
"filmigratis": "https://filmigratis.org", "filmigratis": "https://filmigratis.org",
"filmsenzalimiticc": "https://www.filmsenzalimiti01.xyz", "filmsenzalimiticc": "https://www.filmsenzalimiti01.website",
"filmstreaming01": "https://filmstreaming01.com", "filmstreaming01": "https://filmstreaming01.com",
"guardaserie_stream": "https://guardaserie.yoga", "guardaserie_stream": "https://guardaserie.yoga",
"guardaseriecam": "https://guardaserie.cam", "guardaseriecam": "https://guardaserie.cam",
"guardaserieclick": "https://www.guardaserie.plus", "guardaserieclick": "https://www.guardaserie.vision",
"guardaserieicu": "https://guardaserie.cloud", "guardaserieicu": "https://guardaserie.world",
"hd4me": "https://hd4me.net", "hd4me": "https://hd4me.net",
"ilcorsaronero": "https://ilcorsaronero.link", "ilcorsaronero": "https://ilcorsaronero.link",
"ilgeniodellostreaming": "https://ilgeniodellostreaming.soy", "ilgeniodellostreaming": "https://ilgeniodellostreaming.moe",
"ilgeniodellostreaming_cam": "https://ilgeniodellostreaming.gold", "ilgeniodellostreaming_cam": "https://ilgeniodellostreaming.photo",
"italiaserie": "https://italiaserie.fit", "italiaserie": "https://italiaserie.casa",
"mediasetplay": "https://www.mediasetplay.mediaset.it", "mediasetplay": "https://www.mediasetplay.mediaset.it",
"mondoserietv": "https://mondoserietv.fun", "mondoserietv": "https://mondoserietv.fun",
"paramount": "https://www.paramountnetwork.it", "paramount": "https://www.paramountnetwork.it",
"piratestreaming": "https://www.piratestreaming.guru", "piratestreaming": "https://www.piratestreaming.codes",
"polpotv": "https://roma.polpo.tv", "polpotv": "https://roma.polpo.tv",
"raiplay": "https://www.raiplay.it", "raiplay": "https://www.raiplay.it",
"serietvonline": "https://serietvonline.pink", "serietvonline": "https://serietvonline.blue",
"serietvsubita": "http://serietvsubita.xyz", "serietvsubita": "http://serietvsubita.xyz",
"serietvu": "https://www.serietvu.link", "serietvu": "https://www.serietvu.link",
"streamingcommunity": "https://streamingcommunity.co", "streamingcommunity": "https://streamingcommunity.co",
+11
View File
@@ -0,0 +1,11 @@
{
"id": "accuradio",
"name": "AccuRadio",
"active": true,
"language": ["*"],
"thumbnail": "accuradio.png",
"banner": "accuradio.png",
"categories": ["music"],
"not_active":["include_in_global_search"],
"settings" :[]
}
+87
View File
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Canale per accuradio
# ------------------------------------------------------------
import random
from core import httptools, support
from platformcode import logger
host = 'https://www.accuradio.com'
api_url = host + '/c/m/json/{}/'
headers = [['Referer', host]]
def mainlist(item):
itemlist = []
item.action = 'peliculas'
js = httptools.downloadpage(api_url.format('brands')).json
for it in js.get('features',[]):
itemlist.append(
item.clone(url= '{}/{}'.format(host,it.get('canonical_url','')),
title=support.typo(it['name'],'italic') + support.typo(it.get('channels',''),'_ [] color kod')
))
for it in js.get('brands',[]):
itemlist.append(
item.clone(url= '{}/{}'.format(host,it.get('canonical_url','')),
title=support.typo(it['name'],'bullet bold') + support.typo(it.get('channels',''),'_ [] color kod')
))
itemlist.append(item.clone(title=support.typo('Cerca...', 'bold color kod'), action='search', thumbnail=support.thumb('search')))
support.channel_config(item, itemlist)
return itemlist
@support.scrape
def peliculas(item):
action = 'playradio'
patron = r'data-id="(?P<id>[^"]+)"\s*data-oldid="(?P<oldid>[^"]+)".*?data-name="(?P<title>[^"]+)(?:[^>]+>){5}<img class="[^"]+"\s*src="(?P<thumb>[^"]+)(?:[^>]+>){6}\s*(?P<plot>[^<]+)'
return locals()
def playradio(item):
import xbmcgui, xbmc
items = httptools.downloadpage('{}/playlist/json/{}/?ando={}&rand={}'.format(host, item.id, item.oldid, random.random())).json
playlist = xbmc.PlayList(xbmc.PLAYLIST_MUSIC)
playlist.clear()
for i in items:
if 'id' in i:
url = i['primary'] + i['fn'] + '.m4a'
title = i['title']
artist = i['track_artist']
album = i['album']['title']
year = i['album']['year']
thumb = 'https://www.accuradio.com/static/images/covers300' + i['album']['cdcover']
duration = i.get('duration',0)
info = {'duration':duration,
'album':album,
'artist':artist,
'title':title,
'year':year,
'mediatype':'music'}
item = xbmcgui.ListItem(title, path=url)
item.setArt({'thumb':thumb, 'poster':thumb, 'icon':thumb})
item.setInfo('music',info)
playlist.add(url, item)
xbmc.Player().play(playlist)
def search(item, text):
support.info(text)
item.url = host + '/search/' + text
itemlist = []
try:
data = support.match(item.url).data
artists = support.match(data, patronBlock=r'artistResults(.*?)</ul', patron=r'href="(?P<url>[^"]+)"\s*>(?P<title>[^<]+)').matches
if artists:
for url, artist in artists:
itemlist.append(item.clone(title=support.typo(artist,'bullet bold'), thumbnail=support.thumb('music'), url=host+url, action='peliculas'))
item.data = data
itemlist += peliculas(item)
# Continua la ricerca in caso di errore
except:
import sys
for line in sys.exc_info():
logger.error("%s" % line)
return itemlist
+2 -2
View File
@@ -77,8 +77,8 @@ def peliculas(item):
item.title += support.typo(item.lang2, '_ [] color kod') item.title += support.typo(item.lang2, '_ [] color kod')
if item.args == 'update': if item.args == 'update':
item.title = item.title.replace('-', ' ') item.title = item.title.replace('-', ' ')
if item.args == 'search': # if item.args == 'search':
item.contentType = 'tvshow' if 'serie-' in item.url else 'movie' # item.contentType = 'tvshow' if 'serie-' in item.url else 'movie'
return item return item
+4 -3
View File
@@ -186,9 +186,10 @@ def play(item):
if item.contentType == 'episode': data = session.get('{}/playback/v2/videoPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{}) if item.contentType == 'episode': data = session.get('{}/playback/v2/videoPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{})
else: data = session.get('{}/playback/v2/channelPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{}) else: data = session.get('{}/playback/v2/channelPlaybackInfo/{}?usePreAuth=true'.format(api, item.id), headers=headers).json().get('data',{}).get('attributes',{})
if data.get('protection', {}).get('drm_enabled',True): if data.get('protection', {}).get('drm_enabled',True):
url = data['streaming']['dash']['url'] item.url = data['streaming']['dash']['url']
item.drm = 'com.widevine.alpha' item.drm = 'com.widevine.alpha'
item.license = data['protection']['schemes']['widevine']['licenseUrl'] + '|PreAuthorization=' + data['protection']['drmToken'] + '|R{SSM}|' item.license = data['protection']['schemes']['widevine']['licenseUrl'] + '|PreAuthorization=' + data['protection']['drmToken'] + '|R{SSM}|'
else: else:
url = data['streaming']['hls']['url'] item.url = data['streaming']['hls']['url']
return support.servertools.find_video_items(item, data=url) item.manifest = 'hls'
return [item]
-1
View File
@@ -115,7 +115,6 @@ def select(item):
def search(item, texto): def search(item, texto):
support.info() support.info()
item.url = host + "/?s=" + texto item.url = host + "/?s=" + texto
item.contentType = 'episode'
item.args = 'search' item.args = 'search'
try: try:
return peliculas(item) return peliculas(item)
+7 -2
View File
@@ -157,12 +157,17 @@ def episodios(item):
def findvideos(item): def findvideos(item):
logger.debug() logger.debug()
return support.server(item, item.url, Download=False) return support.server(item, itemlist=[item.clone(title='Paramount', server='directo', action='play')], Download=False)
def play(item): def play(item):
logger.debug() logger.debug()
item.server = 'paramount_server' item.manifest = 'hls'
mgid = support.match(item.url, patron=r'uri":"([^"]+)"').match
url = 'https://media.mtvnservices.com/pmt/e1/access/index.html?uri=' + mgid + '&configtype=edge&ref=' + item.url
ID, rootUrl = support.match(url, patron=[r'"id":"([^"]+)",',r'brightcove_mediagenRootURL":"([^"]+)"']).matches
item.url = jsontools.load(support.match(rootUrl.replace('&device={device}','').format(uri = ID)).data)['package']['video']['item'][0]['rendition'][0]['src']
if item.livefilter: if item.livefilter:
d = liveDict()[item.livefilter] d = liveDict()[item.livefilter]
item = item.clone(title=support.typo(item.livefilter, 'bold'), fulltitle=item.livefilter, url=d['url'], plot=d['plot'], action='play', forcethumb=True, no_return=True) item = item.clone(title=support.typo(item.livefilter, 'bold'), fulltitle=item.livefilter, url=d['url'], plot=d['plot'], action='play', forcethumb=True, no_return=True)
+8 -3
View File
@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# ------------------------------------------------------------ # ------------------------------------------------------------
# Canale per altadefinizione01 # Canale per tunein
# ------------------------------------------------------------ # ------------------------------------------------------------
from core import support from core import scrapertools, support
from platformcode import logger
host = 'http://api.radiotime.com' host = 'http://api.radiotime.com'
headers = [['Referer', host]] headers = [['Referer', host]]
@@ -32,6 +33,7 @@ def radio(item):
data = support.match(item, patron= r'text="(?P<title>[^\("]+)(?:\((?P<location>[^\)]+)\))?" URL="(?P<url>[^"]+)" bitrate="(?P<quality>[^"]+)" reliability="[^"]+" guide_id="[^"]+" subtext="(?P<song>[^"]+)" genre_id="[^"]+" formats="(?P<type>[^"]+)" (?:playing="[^"]+" )?(?:playing_image="[^"]+" )?(?:show_id="[^"]+" )?(?:item="[^"]+" )?image="(?P<thumb>[^"]+)"') data = support.match(item, patron= r'text="(?P<title>[^\("]+)(?:\((?P<location>[^\)]+)\))?" URL="(?P<url>[^"]+)" bitrate="(?P<quality>[^"]+)" reliability="[^"]+" guide_id="[^"]+" subtext="(?P<song>[^"]+)" genre_id="[^"]+" formats="(?P<type>[^"]+)" (?:playing="[^"]+" )?(?:playing_image="[^"]+" )?(?:show_id="[^"]+" )?(?:item="[^"]+" )?image="(?P<thumb>[^"]+)"')
if data.matches: if data.matches:
for title, location, url, quality, song, type, thumbnail in data.matches: for title, location, url, quality, song, type, thumbnail in data.matches:
title = scrapertools.unescape(title)
itemlist.append( itemlist.append(
item.clone(title = support.typo(title, 'bold') + support.typo(quality + ' kbps','_ [] bold color kod'), item.clone(title = support.typo(title, 'bold') + support.typo(quality + ' kbps','_ [] bold color kod'),
thumbnail = thumbnail, thumbnail = thumbnail,
@@ -43,6 +45,7 @@ def radio(item):
matches = support.match(data.data, patron= r'text="(?P<title>[^\("]+)(?:\([^\)]+\))?" URL="(?P<url>[^"]+)" (?:guide_id="[^"]+" )?(?:stream_type="[^"]+" )?topic_duration="(?P<duration>[^"]+)" subtext="(?P<plot>[^"]+)" item="[^"]+" image="(?P<thumb>[^"]+)"').matches matches = support.match(data.data, patron= r'text="(?P<title>[^\("]+)(?:\([^\)]+\))?" URL="(?P<url>[^"]+)" (?:guide_id="[^"]+" )?(?:stream_type="[^"]+" )?topic_duration="(?P<duration>[^"]+)" subtext="(?P<plot>[^"]+)" item="[^"]+" image="(?P<thumb>[^"]+)"').matches
if matches: if matches:
for title, url, duration, plot, thumbnail in matches: for title, url, duration, plot, thumbnail in matches:
title = scrapertools.unescape(title)
infoLabels={} infoLabels={}
infoLabels['duration'] = duration infoLabels['duration'] = duration
itemlist.append( itemlist.append(
@@ -56,12 +59,14 @@ def radio(item):
else: else:
matches = support.match(data.data, patron= r'text="(?P<title>[^"]+)" URL="(?P<url>[^"]+)"').matches matches = support.match(data.data, patron= r'text="(?P<title>[^"]+)" URL="(?P<url>[^"]+)"').matches
for title, url in matches: for title, url in matches:
title = scrapertools.unescape(title)
itemlist.append( itemlist.append(
item.clone(channel = item.channel, item.clone(channel = item.channel,
title = support.typo(title, 'bold'), title = support.typo(title, 'bold'),
thumbnail = item.thumbnail, thumbnail = item.thumbnail,
url = url, url = url,
action = 'radio')) action = 'radio'))
support.nextPage(itemlist, item, data.data, r'(?P<url>[^"]+)" key="nextStations')
return itemlist return itemlist
@@ -86,5 +91,5 @@ def search(item, text):
except: except:
import sys import sys
for line in sys.exc_info(): for line in sys.exc_info():
support.logger.error("%s" % line) logger.error("%s" % line)
return [] return []
+1 -1
View File
@@ -23,7 +23,7 @@ except:
conn_id = '' conn_id = ''
main_host = host + '/vvvvid/ondemand/' main_host = host + '/vvvvid/ondemand/'
@support.menu @support.menu
+6 -2
View File
@@ -104,6 +104,7 @@ def unescape(text):
from Fredrik Lundh from Fredrik Lundh
http://effbot.org/zone/re-sub.htm#unescape-html http://effbot.org/zone/re-sub.htm#unescape-html
""" """
if not ('&' in text and ';' in text): if not ('&' in text and ';' in text):
return text return text
@@ -129,13 +130,16 @@ def unescape(text):
import html.entities as htmlentitydefs import html.entities as htmlentitydefs
else: else:
import htmlentitydefs import htmlentitydefs
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]]).encode("utf-8") ret = unichr(htmlentitydefs.name2codepoint[text[1:-1]]).encode("utf-8")
except KeyError: except KeyError:
logger.error("keyerror") logger.error("keyerror")
pass pass
except: except:
pass pass
return text # leave as is # from core.support import dbg;dbg()
if type(ret) != str:
ret = ret.decode()
return ret # leave as is
return re.sub("&#?\w+;", fixup, str(text)) return re.sub("&#?\w+;", fixup, str(text))
+2 -1
View File
@@ -327,8 +327,8 @@ def filter_list(episodelist, action=None, path=None):
# Make Language List # Make Language List
for episode in episodelist: for episode in episodelist:
if not episode.contentLanguage: episode.contentLanguage = 'ITA'
if type(episode.contentLanguage) == list and episode.contentLanguage not in lang_list: if type(episode.contentLanguage) == list and episode.contentLanguage not in lang_list:
#lang_list = episode.contentLanguage
pass pass
else: else:
if episode.contentLanguage and episode.contentLanguage not in lang_list: if episode.contentLanguage and episode.contentLanguage not in lang_list:
@@ -338,6 +338,7 @@ def filter_list(episodelist, action=None, path=None):
if sub not in sub_list: sub_list.append(sub) if sub not in sub_list: sub_list.append(sub)
else: else:
lang_list.append(episode.contentLanguage) lang_list.append(episode.contentLanguage)
# add to Language List subtitled languages # add to Language List subtitled languages
if sub_list: if sub_list:
for sub in sub_list: for sub in sub_list:
+1 -33
View File
@@ -119,7 +119,7 @@ def get_channel_url(findhostMethod=None, name=None, forceFindhost=False):
name = os.path.basename(frame[0].f_code.co_filename).replace('.py', '') name = os.path.basename(frame[0].f_code.co_filename).replace('.py', '')
if findhostMethod: if findhostMethod:
url = jsontools.get_node_from_file(name, 'url') url = jsontools.get_node_from_file(name, 'url')
if not url or 'web.archive.org' in url or forceFindhost: # per eliminare tutti i webarchive salvati causa bug httptools CF, eliminare in futuro if not url or forceFindhost:
url = findhostMethod(channels_data['findhost'][name]) url = findhostMethod(channels_data['findhost'][name])
jsontools.update_node(url, name, 'url') jsontools.update_node(url, name, 'url')
return url return url
@@ -139,38 +139,6 @@ def get_system_platform():
return platform return platform
def is_autorun_enabled():
try:
if "xbmc.executebuiltin('RunAddon(plugin.video.kod)')" in open(os.path.join(xbmc.translatePath('special://userdata'),'autoexec.py')).read():
return True
else:
return False
except:
# if error in reading from file autoexec doesnt exists
return False
def enable_disable_autorun(is_enabled):
# old method, now using service.py
path = os.path.join(xbmc.translatePath('special://userdata'),'autoexec.py')
append_write = 'a' if os.path.exists(path) else 'w'
if is_enabled is False:
with open(path, append_write) as file:
file.write("import xbmc\nxbmc.executebuiltin('RunAddon(plugin.video.kod)')")
set_setting('autostart', 'On')
else:
file = open(path, "r")
old_content = file.read()
new_content = old_content.replace("xbmc.executebuiltin('RunAddon(plugin.video.kod)')", "")
file.close()
with open(path, "w") as file:
file.write(new_content)
set_setting('autostart', True)
return True
def get_all_settings_addon(): def get_all_settings_addon():
# Read the settings.xml file and return a dictionary with {id: value} # Read the settings.xml file and return a dictionary with {id: value}
from core import scrapertools from core import scrapertools
+2 -5
View File
@@ -151,10 +151,6 @@ def run(item=None):
import urllib import urllib
short = urllib.urlopen('https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read().decode('utf-8') short = urllib.urlopen('https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read().decode('utf-8')
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % short) platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % short)
# Action in certain channel specified in "action" and "channel" parameters
elif item.action == "check_channels":
from platformcode import checkhost
checkhost.check_channels()
else: else:
# Checks if channel exists # Checks if channel exists
if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")): if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")):
@@ -461,7 +457,8 @@ def play_from_library(item):
# Modify the action (currently the video library needs "findvideos" since this is where the sources are searched # Modify the action (currently the video library needs "findvideos" since this is where the sources are searched
item.action = "findvideos" item.action = "findvideos"
window_type = config.get_setting("window_type", "videolibrary") window_type = config.get_setting("window_type", "videolibrary") if config.get_setting('next_ep') < 3 and item.contentType != 'movie' else 1
# and launch kodi again # and launch kodi again
if xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1: if xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1:
xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")") xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")")
+38 -10
View File
@@ -294,6 +294,10 @@ def render_items(itemlist, parent_item):
""" """
Function used to render itemlist on kodi Function used to render itemlist on kodi
""" """
# if it's not a list, do nothing
if not isinstance(itemlist, list):
return
logger.debug('START render_items') logger.debug('START render_items')
thumb_type = config.get_setting('video_thumbnail_type') thumb_type = config.get_setting('video_thumbnail_type')
from platformcode import shortcuts from platformcode import shortcuts
@@ -309,9 +313,6 @@ def render_items(itemlist, parent_item):
check_sf = os.path.exists(sf_file_path) check_sf = os.path.exists(sf_file_path)
superfavourites = check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")') superfavourites = check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")')
# if it's not a list, do nothing
if not isinstance(itemlist, list):
return
# if there's no item, add "no elements" item # if there's no item, add "no elements" item
if not len(itemlist): if not len(itemlist):
itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png'))) itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png')))
@@ -583,7 +584,7 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']: if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']:
context_commands.append(("InfoPlus", "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=infoplus&action=Main&from_channel=' + item.channel))) context_commands.append(("InfoPlus", "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=infoplus&action=Main&from_channel=' + item.channel)))
# Go to the Main Menu (channel.mainlist) # 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.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist" and not parent_item.noMainMenu:
if parent_item.action != "mainlist": 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(0, (config.get_localized_string(60349), "Container.Refresh (%s?%s)" % (sys.argv[0], Item(channel=item.channel, action="mainlist").tourl())))
@@ -609,8 +610,10 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
else: else:
mediatype = item.contentType mediatype = item.contentType
context_commands.append((config.get_localized_string(60350), "Container.Update (%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': 'search', 'action': "from_context", 'from_channel': item.channel, 'contextual': True, 'text': item.wanted})))) if config.get_setting('new_search'):
context_commands.append((config.get_localized_string(60350), "RunPlugin (%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': 'search', 'action': "from_context", 'from_channel': item.channel, 'contextual': True}))))
else:
context_commands.append((config.get_localized_string(60350), "Container.Refresh (%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': 'search', 'action': "from_context", 'from_channel': item.channel, 'contextual': True, 'text': item.wanted}))))
context_commands.append( (config.get_localized_string(70561), "Container.Update (%s?%s&%s)" % (sys.argv[0], item_url, 'channel=search&action=from_context&search_type=list&page=1&list_type=%s/%s/similar' % (mediatype, item.infoLabels['tmdb_id'])))) context_commands.append( (config.get_localized_string(70561), "Container.Update (%s?%s&%s)" % (sys.argv[0], item_url, 'channel=search&action=from_context&search_type=list&page=1&list_type=%s/%s/similar' % (mediatype, item.infoLabels['tmdb_id']))))
if item.channel != "videolibrary" and item.videolibrary != False: if item.channel != "videolibrary" and item.videolibrary != False:
@@ -642,7 +645,7 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
# Search trailer... # Search trailer...
if (item.contentTitle and item.contentType in ['movie', 'tvshow']) or "buscar_trailer" in context: 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)" % (sys.argv[0], urllib.urlencode({ 'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.contentTitle if item.contentTitle else item.fulltitle, 'contextual': True})))) 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'): if kwargs.get('superfavourites'):
context_commands.append((config.get_localized_string(60361), "RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)")) context_commands.append((config.get_localized_string(60361), "RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)"))
@@ -936,8 +939,8 @@ def get_dialogo_opciones(item, default_action, strm, autoplay):
if default_action == 3: if default_action == 3:
seleccion = len(opciones) - 1 seleccion = len(opciones) - 1
# Search for trailers on youtube # Search for trailers
if item.channel not in ["Trailer", "ecarteleratrailers"]: if item.channel not in ["trailertools"]:
# "Search Trailer" # "Search Trailer"
opciones.append(config.get_localized_string(30162)) opciones.append(config.get_localized_string(30162))
@@ -1094,6 +1097,7 @@ def set_player(item, xlistitem, mediaurl, view, strm):
playlist.add(mediaurl, xlistitem) playlist.add(mediaurl, xlistitem)
# Reproduce # Reproduce
xbmc_player.play(playlist, xlistitem) xbmc_player.play(playlist, xlistitem)
add_next_to_playlist(item)
if config.get_setting('trakt_sync'): if config.get_setting('trakt_sync'):
from core import trakt_tools from core import trakt_tools
@@ -1129,6 +1133,29 @@ def set_player(item, xlistitem, mediaurl, view, strm):
xbmcgui.Window(12005).show() xbmcgui.Window(12005).show()
def add_next_to_playlist(item):
import threading
from core import filetools, videolibrarytools
from platformcode import xbmc_videolibrary
def add_to_playlist(item):
if item.contentType != 'movie' and item.strm_path:
next= xbmc_videolibrary.next_ep(item)
if next:
next.back = True
nfo_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"), next.strm_path.replace('strm','nfo'))
if nfo_path and filetools.isfile(nfo_path):
head_nfo, item_nfo = videolibrarytools.read_nfo(nfo_path)
nextItem = xbmcgui.ListItem(path=item_nfo.url)
nextItem.setArt({"thumb": item_nfo.contentThumbnail if item_nfo.contentThumbnail else item_nfo.thumbnail})
set_infolabels(nextItem, item_nfo, True)
nexturl = "plugin://plugin.video.kod/?" + next.tourl()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.add(nexturl, nextItem)
add_to_playlist(next)
if item.contentType != 'movie' and config.get_setting('next_ep') == 3:
threading.Thread(target=add_to_playlist, args=[item]).start()
def torrent_client_installed(show_tuple=False): def torrent_client_installed(show_tuple=False):
# External plugins found in servers / torrent.json node clients # External plugins found in servers / torrent.json node clients
from core import filetools from core import filetools
@@ -1216,7 +1243,8 @@ def resume_playback(played_time):
if action in self.action_exitkeys_id: if action in self.action_exitkeys_id:
self.set_values(False) self.set_values(False)
self.close() self.close()
if played_time:
if played_time and played_time > 30:
Dialog = ResumePlayback('ResumePlayback.xml', config.get_runtime_path(), played_time=played_time) Dialog = ResumePlayback('ResumePlayback.xml', config.get_runtime_path(), played_time=played_time)
Dialog.show() Dialog.show()
t = 0 t = 0
+10 -9
View File
@@ -25,8 +25,6 @@ def mark_auto_as_watched(item):
logger.debug() logger.debug()
actual_time = 0 actual_time = 0
total_time = 0 total_time = 0
# logger.debug("item:\n" + item.tostring('\n'))
# if item.options['continue']: item.played_time = platformtools.resume_playback(platformtools.get_played_time(item))
time_limit = time.time() + 30 time_limit = time.time() + 30
while not platformtools.is_playing() and time.time() < time_limit: while not platformtools.is_playing() and time.time() < time_limit:
@@ -40,7 +38,7 @@ def mark_auto_as_watched(item):
percentage = float(config.get_setting("watched_setting")) / 100 percentage = float(config.get_setting("watched_setting")) / 100
time_from_end = config.get_setting('next_ep_seconds') time_from_end = config.get_setting('next_ep_seconds')
if item.contentType != 'movie' and config.get_setting('next_ep'): if item.contentType != 'movie' and config.get_setting('next_ep') < 3:
next_dialogs = ['NextDialog.xml', 'NextDialogExtended.xml', 'NextDialogCompact.xml'] next_dialogs = ['NextDialog.xml', 'NextDialogExtended.xml', 'NextDialogCompact.xml']
next_ep_type = config.get_setting('next_ep_type') next_ep_type = config.get_setting('next_ep_type')
ND = next_dialogs[next_ep_type] ND = next_dialogs[next_ep_type]
@@ -49,8 +47,10 @@ def mark_auto_as_watched(item):
logger.debug(next_episode) logger.debug(next_episode)
while platformtools.is_playing(): while platformtools.is_playing():
actual_time = xbmc.Player().getTime() try: actual_time = xbmc.Player().getTime()
total_time = xbmc.Player().getTotalTime() except: pass
try: total_time = xbmc.Player().getTotalTime()
except: pass
if item.played_time and xbmcgui.getCurrentWindowId() == 12005: if item.played_time and xbmcgui.getCurrentWindowId() == 12005:
xbmc.Player().seekTime(item.played_time) xbmc.Player().seekTime(item.played_time)
item.played_time = 0 # Fix for Slow Devices item.played_time = 0 # Fix for Slow Devices
@@ -75,7 +75,6 @@ def mark_auto_as_watched(item):
# check for next Episode # check for next Episode
if next_episode and sync and time_from_end >= difference: if next_episode and sync and time_from_end >= difference:
nextdialog = NextDialog(ND, config.get_runtime_path()) nextdialog = NextDialog(ND, config.get_runtime_path())
nextdialog.show()
while platformtools.is_playing() and not nextdialog.is_exit(): while platformtools.is_playing() and not nextdialog.is_exit():
xbmc.sleep(100) xbmc.sleep(100)
if nextdialog.continuewatching: if nextdialog.continuewatching:
@@ -83,10 +82,9 @@ def mark_auto_as_watched(item):
xbmc.Player().stop() xbmc.Player().stop()
nextdialog.close() nextdialog.close()
break break
xbmc.sleep(1000)
# if item.options['continue']: # if item.options['continue']:
if 10 < actual_time < mark_time: if actual_time < mark_time:
item.played_time = actual_time item.played_time = actual_time
else: item.played_time = 0 else: item.played_time = 0
platformtools.set_played_time(item) platformtools.set_played_time(item)
@@ -96,13 +94,16 @@ def mark_auto_as_watched(item):
while platformtools.is_playing(): while platformtools.is_playing():
xbmc.sleep(100) xbmc.sleep(100)
if not show_server and item.play_from != 'window' and not item.no_return: if not show_server and item.play_from != 'window' and not item.no_return:
xbmc.sleep(700) xbmc.sleep(700)
xbmc.executebuiltin('Action(ParentDir)') xbmc.executebuiltin('Action(ParentDir)')
xbmc.sleep(500) xbmc.sleep(500)
if next_episode and next_episode.next_ep and config.get_setting('next_ep') == 1: if next_episode and next_episode.next_ep and config.get_setting('next_ep') == 1:
from platformcode.launcher import play_from_library from platformcode.launcher import play_from_library
play_from_library(next_episode) play_from_library(next_episode)
# db need to be closed when not used, it will cause freezes # db need to be closed when not used, it will cause freezes
from core import db from core import db
db.close() db.close()
@@ -1368,7 +1369,6 @@ def next_ep(item):
return item return item
class NextDialog(xbmcgui.WindowXMLDialog): class NextDialog(xbmcgui.WindowXMLDialog):
item = None item = None
cancel = False cancel = False
@@ -1393,6 +1393,7 @@ class NextDialog(xbmcgui.WindowXMLDialog):
self.setProperty("next_img", img) self.setProperty("next_img", img)
self.setProperty("title", info["tvshowtitle"]) self.setProperty("title", info["tvshowtitle"])
self.setProperty("ep_title", "%dx%02d - %s" % (info["season"], info["episode"], info["title"])) self.setProperty("ep_title", "%dx%02d - %s" % (info["season"], info["episode"], info["title"]))
self.doModal()
def set_exit(self, EXIT): def set_exit(self, EXIT):
self.EXIT = EXIT self.EXIT = EXIT
@@ -1425,7 +1425,7 @@ msgid "The unzipped %s file already exists, or you want to overwrite it.?"
msgstr "" msgstr ""
msgctxt "#60305" msgctxt "#60305"
msgid "" msgid "[COLOR red]Do not open this link[/COLOR]"
msgstr "" msgstr ""
msgctxt "#60306" msgctxt "#60306"
@@ -1437,7 +1437,7 @@ msgid "Use 'Preferences' to change your password"
msgstr "" msgstr ""
msgctxt "#60308" msgctxt "#60308"
msgid "" msgid "[COLOR red]It's one use, so write it[/COLOR]"
msgstr "" msgstr ""
msgctxt "#60309" msgctxt "#60309"
@@ -1541,7 +1541,7 @@ msgid "Configuration"
msgstr "" msgstr ""
msgctxt "#60334" msgctxt "#60334"
msgid "" msgid "Log file too large. Restart Kodi and retry"
msgstr "" msgstr ""
msgctxt "#60335" msgctxt "#60335"
@@ -4809,7 +4809,7 @@ msgid "Notification(Update Kodi to its latest version, for best info,8000, 'http
msgstr "" msgstr ""
msgctxt "#70501" msgctxt "#70501"
msgid "Search did not match (%s)" msgid "Search did not match"
msgstr "" msgstr ""
msgctxt "#70502" msgctxt "#70502"
@@ -4841,11 +4841,11 @@ msgid "Search in Mymovies"
msgstr "" msgstr ""
msgctxt "#70510" msgctxt "#70510"
msgid "Manual Search in Youtube" msgid "Manual Search"
msgstr "" msgstr ""
msgctxt "#70511" msgctxt "#70511"
msgid "Manual Search in Mymovies" msgid ""
msgstr "" msgstr ""
msgctxt "#70512" msgctxt "#70512"
@@ -4853,11 +4853,11 @@ msgid "Searching in Mymovies"
msgstr "" msgstr ""
msgctxt "#70513" msgctxt "#70513"
msgid "Manual Searching in Filmaffinity" msgid ""
msgstr "" msgstr ""
msgctxt "#70514" msgctxt "#70514"
msgid "Manual Search in Jayhap" msgid ""
msgstr "" msgstr ""
msgctxt "#70515" msgctxt "#70515"
@@ -6129,11 +6129,15 @@ msgstr ""
msgctxt "#70832" msgctxt "#70832"
msgid "Disabled" msgid "Disabled"
msgstr "Disabilitato" msgstr ""
msgctxt "#70833" msgctxt "#70833"
msgid "Automatic" msgid "Automatic"
msgstr "Automatico" msgstr ""
msgctxt "#70834"
msgid "Playlist"
msgstr ""
# DNS start [ settings and declaration ] # DNS start [ settings and declaration ]
msgctxt "#707401" msgctxt "#707401"
@@ -1424,8 +1424,8 @@ msgid "The unzipped %s file already exists, or you want to overwrite it.?"
msgstr "il file %s da decomprimere esiste già, vuoi sovrascriverlo?" msgstr "il file %s da decomprimere esiste già, vuoi sovrascriverlo?"
msgctxt "#60305" msgctxt "#60305"
msgid "" msgid "[COLOR red]Do not open this link[/COLOR]"
msgstr "" msgstr "[COLOR red]NON aprire questo link[/COLOR]"
msgctxt "#60306" msgctxt "#60306"
msgid "The fields 'New password' and 'Confirm new password' do not match" msgid "The fields 'New password' and 'Confirm new password' do not match"
@@ -1436,8 +1436,8 @@ msgid "Use 'Preferences' to change your password"
msgstr "Entra in 'Preferenze' per cambiare la password" msgstr "Entra in 'Preferenze' per cambiare la password"
msgctxt "#60308" msgctxt "#60308"
msgid "" msgid "[COLOR red]It's one use, so write it[/COLOR]"
msgstr "" msgstr "[COLOR red]Funziona una volta sola, quindi scrivilo[/COLOR]"
msgctxt "#60309" msgctxt "#60309"
msgid "The password is not correct." msgid "The password is not correct."
@@ -1540,8 +1540,8 @@ msgid "Configuration"
msgstr "Configurazione" msgstr "Configurazione"
msgctxt "#60334" msgctxt "#60334"
msgid "" msgid "Log file too large. Restart Kodi and retry"
msgstr "" msgstr "File di log troppo pesante. Riapri kodi e riprova"
msgctxt "#60335" msgctxt "#60335"
msgid "Watch in..." msgid "Watch in..."
@@ -4808,8 +4808,8 @@ msgid "Notification(Update Kodi to its latest version, for best info,8000, 'http
msgstr "Notification(Aggiorna Kodi alla sua ultima versione, per migliori info,8000, 'http://i.imgur.com/mHgwcn3.png')" msgstr "Notification(Aggiorna Kodi alla sua ultima versione, per migliori info,8000, 'http://i.imgur.com/mHgwcn3.png')"
msgctxt "#70501" msgctxt "#70501"
msgid "Search did not match (%s)" msgid "Search did not match"
msgstr "La ricerca non ha dato risultati (%s)" msgstr "La ricerca non ha dato risultati"
msgctxt "#70502" msgctxt "#70502"
msgid ">> Next" msgid ">> Next"
@@ -4840,24 +4840,24 @@ msgid "Search in Mymovies"
msgstr "Ricerca in Mymovies" msgstr "Ricerca in Mymovies"
msgctxt "#70510" msgctxt "#70510"
msgid "Manual Search in Youtube" msgid "Manual Search"
msgstr "Ricerca Manuale in Youtube" msgstr "Ricerca Manuale"
msgctxt "#70511" msgctxt "#70511"
msgid "Manual Search in Mymovies" msgid ""
msgstr "Ricerca Manuale in Mymovies" msgstr ""
msgctxt "#70512" msgctxt "#70512"
msgid "Searching in Mymovies" msgid "Searching in Mymovies"
msgstr "Ricerca in Mymovies" msgstr "Ricerca in Mymovies"
msgctxt "#70513" msgctxt "#70513"
msgid "Manual Searching in Filmaffinity" msgid ""
msgstr "Ricerca Manuale in Filmaffinity" msgstr ""
msgctxt "#70514" msgctxt "#70514"
msgid "Manual Search in Jayhap" msgid ""
msgstr "Ricerca Manuale in Jayhap" msgstr ""
msgctxt "#70515" msgctxt "#70515"
msgid "Completed %s" msgid "Completed %s"
@@ -6136,6 +6136,10 @@ msgctxt "#70833"
msgid "Automatic" msgid "Automatic"
msgstr "Automatico" msgstr "Automatico"
msgctxt "#70834"
msgid "Playlist"
msgstr "Playlist"
# DNS start [ settings and declaration ] # DNS start [ settings and declaration ]
msgctxt "#707401" msgctxt "#707401"
msgid "Enable DNS check alert" msgid "Enable DNS check alert"
+1 -1
View File
@@ -39,7 +39,7 @@
<setting id="videolibrary_kodi" type="bool" label="70120" default="false"/> <setting id="videolibrary_kodi" type="bool" label="70120" default="false"/>
<setting label="59997" type="lsep"/> <setting label="59997" type="lsep"/>
<setting id="videolibrary_max_quality" type="bool" label="70729" default="false" visible="true"/> <setting id="videolibrary_max_quality" type="bool" label="70729" default="false" visible="true"/>
<setting id="next_ep" type="select" label="70748" lvalues="70832|70833|70732" default="1"/> <setting id="next_ep" type="select" label="70748" lvalues="70832|70833|70732|70834" default="1"/>
<setting id="next_ep_type" type="select" label="70754" lvalues="70755|70756|70757" default="0" visible="!eq(-1,0)" subsetting="true"/> <setting id="next_ep_type" type="select" label="70754" lvalues="70755|70756|70757" default="0" visible="!eq(-1,0)" subsetting="true"/>
<setting id="next_ep_seconds" type="slider" option="int" range="20,10,240" label="70749" default="40" visible="!eq(-2,0)" subsetting="true"/> <setting id="next_ep_seconds" type="slider" option="int" range="20,10,240" label="70749" default="40" visible="!eq(-2,0)" subsetting="true"/>
<setting id="watched_setting" type="slider" option="int" range="20,5,90" label="60634" default="80"/> <setting id="watched_setting" type="slider" option="int" range="20,5,90" label="60634" default="80"/>
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"active": true, "active": false,
"find_videos": { "find_videos": {
"ignore_urls": [], "ignore_urls": [],
"patterns": [ "patterns": [
+1 -1
View File
@@ -12,7 +12,7 @@ def test_video_exists(page_url):
logger.debug("(page_url='%s')" % page_url) logger.debug("(page_url='%s')" % page_url)
global data global data
data = httptools.downloadpage(page_url).data data = httptools.downloadpage(page_url).data
if "<h2>WE ARE SORRY</h2>" in data or '<title>404 Not Found</title>' in data: if "as it expired or has been deleted" in data:
return False, config.get_localized_string(70449) % "UPstream" return False, config.get_localized_string(70449) % "UPstream"
return True, "" return True, ""
+9 -19
View File
@@ -16,24 +16,14 @@ def test_video_exists(page_url):
def get_video_url(page_url, premium=False, user="", password="", video_password=""): def get_video_url(page_url, premium=False, user="", password="", video_password=""):
logger.debug("url=" + page_url) logger.debug("url=" + page_url)
video_urls = []
global data global data
return support.get_jwplayer_mediaurl(data, 'VUP') matches = support.get_jwplayer_mediaurl(data, 'VUP')
# patron = r'sources:\s*\[\{src:\s*"([^"]+)"' if not matches:
# matches = scrapertools.find_multiple_matches(data, patron) data = scrapertools.find_single_match(data, r"<script type='text/javascript'>(eval.function.p,a,c,k,e,.*?)\s*</script>")
# if not matches: if data:
# data = scrapertools.find_single_match(data, r"<script type='text/javascript'>(eval.function.p,a,c,k,e,.*?)\s*</script>") from lib import jsunpack
# if data: data = jsunpack.unpack(data)
# from lib import jsunpack matches = support.get_jwplayer_mediaurl(data, 'VUP')
# data = jsunpack.unpack(data)
# matches = scrapertools.find_multiple_matches(data, patron) return matches
# for url in matches:
# quality = 'm3u8'
# video_url = url
# if 'label' in url:
# url = url.split(',')
# video_url = url[0]
# quality = url[1].replace('label:','')
# video_urls.append(['VUP Player [%s]' % quality, video_url.replace(',','')])
# return video_urls
-3
View File
@@ -458,9 +458,6 @@ if __name__ == "__main__":
if config.get_setting('autostart'): if config.get_setting('autostart'):
xbmc.executebuiltin('RunAddon(plugin.video.' + config.PLUGIN_NAME + ')') xbmc.executebuiltin('RunAddon(plugin.video.' + config.PLUGIN_NAME + ')')
# handling old autoexec method
if config.is_autorun_enabled():
config.enable_disable_autorun(True)
# port old db to new # port old db to new
old_db_name = filetools.join(config.get_data_path(), "kod_db.sqlite") old_db_name = filetools.join(config.get_data_path(), "kod_db.sqlite")
if filetools.isfile(old_db_name): if filetools.isfile(old_db_name):
+5
View File
@@ -343,6 +343,11 @@ class SearchWindow(xbmcgui.WindowXML):
and self.item.infoLabels['year']: and self.item.infoLabels['year']:
logger.debug('retring adding year on channel ' + channel) logger.debug('retring adding year on channel ' + channel)
dummy, valid, dummy = search(self.item.text + " " + str(self.item.infoLabels['year'])) dummy, valid, dummy = search(self.item.text + " " + str(self.item.infoLabels['year']))
# some channels may use original title
if self.item.mode != 'all' and not valid and self.item.infoLabels.get('originaltitle'):
logger.debug('retring with original title on channel ' + channel)
dummy, valid, dummy = search(self.item.infoLabels.get('originaltitle'))
except: except:
pass pass
+4
View File
@@ -749,6 +749,10 @@ def from_context(item):
else: else:
return return
if config.get_setting('new_search'):
from specials import globalsearch
return globalsearch.Search(item)
if 'list_type' not in item: if 'list_type' not in item:
if 'wanted' in item: if 'wanted' in item:
item.title = item.wanted item.title = item.wanted
+93 -51
View File
@@ -836,9 +836,15 @@ def report_menu(item):
action = 'call_browser' action = 'call_browser'
url = item.url url = item.url
itemlist.append(Item(channel=item.channel, action=action, itemlist.append(Item(channel=item.channel, action=action,
title="**- LOG: [COLOR gold]%s[/COLOR] -**" % item.url, url=url, title="LOG: [COLOR gold]%s[/COLOR]" % item.url, url=url,
thumbnail=thumb_next, unify=False, folder=False)) thumbnail=thumb_next, unify=False, folder=False))
if item.one_use:
itemlist.append(Item(channel=item.channel, action="",
title=config.get_localized_string(60305),
thumbnail=thumb_next, folder=False))
itemlist.append(Item(channel=item.channel, action="",
title=config.get_localized_string(60308),
thumbnail=thumb_next, folder=False))
itemlist.append(Item(channel=item.channel, action="call_browser", itemlist.append(Item(channel=item.channel, action="call_browser",
title="su Github (raccomandato)", url='https://github.com/kodiondemand/addon/issues', title="su Github (raccomandato)", url='https://github.com/kodiondemand/addon/issues',
thumbnail=thumb_next, thumbnail=thumb_next,
@@ -847,14 +853,6 @@ def report_menu(item):
url='https://t.me/kodiondemand', title="Su telegram", url='https://t.me/kodiondemand', title="Su telegram",
thumbnail=thumb_next, unify=False, folder=False)) thumbnail=thumb_next, unify=False, folder=False))
if item.one_use:
itemlist.append(Item(channel=item.channel, action="",
title="[COLOR orange]NO ACCEDA al INFORME: se BORRARÁ[/COLOR]",
thumbnail=thumb_next, folder=False))
itemlist.append(Item(channel=item.channel, action="",
title="[COLOR orange]ya que es de un solo uso[/COLOR]",
thumbnail=thumb_next, folder=False))
return itemlist return itemlist
@@ -917,33 +915,34 @@ def report_send(item, description='', fatal=False):
# directly on the forum. If it is a size problem, you are asked to reset Kodi and redo the fault, to # directly on the forum. If it is a size problem, you are asked to reset Kodi and redo the fault, to
# that the LOG is smaller. # that the LOG is smaller.
pastebin_list = { pastebin_list = {
'hastebin': ('1', 'https://hastebin.com/', 'documents', 'random', '', '', 'hastebin': ('1', 'https://hastebin.com/', 'documents', 'random', '', '',
'data', 'json', 'key', '', '0.29', '10', True, 'raw/', '', ''), 'data', 'json', 'key', '', '0.29', '10', True, 'raw/', '', ''),
'dpaste': ('1', 'http://dpaste.com/', 'api/v2/', 'random', 'content=', 'dpaste': ('1', 'http://dpaste.com/', 'api/v2/', 'random', 'content=',
'&syntax=text&title=%s&poster=alfa&expiry_days=7', '&syntax=text&title=%s&poster=alfa&expiry_days=7',
'headers', '', '', 'location', '0.23', '15', True, '', '.txt', ''), 'headers', '', '', 'location', '0.23', '15', True, '', '.txt', ''),
'ghostbin': ('1', 'https://ghostbin.com/', 'paste/new', 'random', 'lang=text&text=', 'ghostbin': ('1', 'https://ghostbin.com/', 'paste/new', 'random', 'lang=text&text=',
'&expire=2d&password=&title=%s', '&expire=2d&password=&title=%s',
'data', 'regex', '<title>(.*?)\s*-\s*Ghostbin<\/title>', '', 'data', 'regex', '<title>(.*?)\s*-\s*Ghostbin<\/title>', '',
'0.49', '15', False, 'paste/', '', ''), '0.49', '15', False, 'paste/', '', ''),
'write.as': ('1', 'https://write.as/', 'api/posts', 'random', 'body=', '&title=%s', 'write.as': ('1', 'https://write.as/', 'api/posts', 'random', 'body=', '&title=%s',
'data', 'json', 'data', 'id', '0.018', '15', True, '', '', ''), 'data', 'json', 'data', 'id', '0.018', '15', True, '', '', ''),
'oneclickpaste': ('1', 'http://oneclickpaste.com/', 'index.php', 'random', 'paste_data=', 'oneclickpaste': ('1', 'http://oneclickpaste.com/', 'index.php', 'random', 'paste_data=',
'&title=%s&format=text&paste_expire_date=1W&visibility=0&pass=&submit=Submit', '&title=%s&format=text&paste_expire_date=1W&visibility=0&pass=&submit=Submit',
'data', 'regex', '<a class="btn btn-primary" href="[^"]+\/(\d+\/)">\s*View\s*Paste\s*<\/a>', 'data', 'regex', '<a class="btn btn-primary" href="[^"]+\/(\d+\/)">\s*View\s*Paste\s*<\/a>',
'', '0.060', '5', True, '', '', ''), '', '0.060', '5', True, '', '', ''),
'bpaste': ('1', 'https://bpaste.net/', '', 'random', 'code=', '&lexer=text&expiry=1week', 'bpaste': ('1', 'https://bpaste.net/', '', 'random', 'code=', '&lexer=text&expiry=1week',
'data', 'regex', 'View\s*<a\s*href="[^*]+/(.*?)">raw<\/a>', '', 'data', 'regex', 'View\s*<a\s*href="[^*]+/(.*?)">raw<\/a>', '',
'0.79', '15', True, 'raw/', '', ''), '0.79', '15', True, 'raw/', '', ''),
'dumpz': ('0', 'http://dumpz.org/', 'api/dump', 'random', 'code=', '&lexer=text&comment=%s&password=', 'dumpz': ('0', 'http://dumpz.org/', 'api/dump', 'random', 'code=', '&lexer=text&comment=%s&password=',
'headers', '', '', 'location', '0.99', '15', False, '', '', ''), 'headers', '', '', 'location', '0.99', '15', False, '', '', ''),
'file.io': ('1', 'https://file.io/', '', 'random', '', 'expires=1w', 'file.io': ('1', 'https://file.io/', '', 'random', '', 'expires=1w',
'requests', 'json', 'key', '', '99.0', '30', False, '', '.log', ''), 'requests', 'json', 'key', '', '99.0', '30', False, '', '', ''),
'uploadfiles': ('1', 'https://up.uploadfiles.io/upload', '', 'random', '', '', 'uploadfiles': ('0', 'https://up.ufile.io/v1/upload', '', 'random', '', '',
'requests', 'json', 'url', '', '99.0', '30', False, None, '', '') 'curl', 'json', 'url', '', '99.0', '30', False, None, '', {'Referer': 'https://ufile.io/'}),
} 'anonfiles': ('1', 'https://api.anonfiles.com/upload', 'upload', 'random', '', '',
'requests', 'json', 'data', 'file,url,short', '99.0', '30', False, None, '', '')
}
pastebin_list_last = ['hastebin', 'ghostbin', 'file.io'] # We leave these services the last pastebin_list_last = ['hastebin', 'ghostbin', 'file.io'] # We leave these services the last
pastebin_one_use = ['file.io'] # Single-use servers and deletes pastebin_one_use = ['file.io'] # Single-use servers and deletes
pastebin_dir = [] pastebin_dir = []
@@ -994,7 +993,7 @@ def report_send(item, description='', fatal=False):
random.shuffle(pastebin_dir) random.shuffle(pastebin_dir)
pastebin_dir.extend(pastebin_list_last) # We leave these services the last pastebin_dir.extend(pastebin_list_last) # We leave these services the last
#pastebin_dir = ['uploadfiles'] # For testing a service # pastebin_dir = ['file.io'] # For testing a service
#log_data = 'TEST FOR SERVICE TESTS' #log_data = 'TEST FOR SERVICE TESTS'
# The list of "pastebin" servers is scrolled to locate an active one, with capacity and availability # The list of "pastebin" servers is scrolled to locate an active one, with capacity and availability
@@ -1018,7 +1017,7 @@ def report_send(item, description='', fatal=False):
paste_file_size = float(pastebin_list[paste_name][10]) # Server capacity in MB paste_file_size = float(pastebin_list[paste_name][10]) # Server capacity in MB
if paste_file_size > 0: # If it is 0, the capacity is unlimited if paste_file_size > 0: # If it is 0, the capacity is unlimited
if log_size > paste_file_size: # Capacity and size verification if log_size > paste_file_size: # Capacity and size verification
msg = 'Log file too large. Restart Kodi and retry' msg = config.get_localized_string(60334)
continue continue
paste_timeout = int(pastebin_list[paste_name][11]) # Timeout for the server paste_timeout = int(pastebin_list[paste_name][11]) # Timeout for the server
paste_random_headers = pastebin_list[paste_name][12] # Do you use RAMDOM headers to mislead the serv? paste_random_headers = pastebin_list[paste_name][12] # Do you use RAMDOM headers to mislead the serv?
@@ -1029,15 +1028,12 @@ def report_send(item, description='', fatal=False):
paste_headers.update(jsontools.load((pastebin_list[paste_name][15]))) paste_headers.update(jsontools.load((pastebin_list[paste_name][15])))
if paste_name in pastebin_one_use: if paste_name in pastebin_one_use:
pastebin_one_use_msg = 'DO NOT ACCESS THE REPORT: it will be DELETED'
item.one_use = True item.one_use = True
else:
pastebin_one_use_msg = ''
try: try:
# POST is created with server options "pastebin" # POST is created with server options "pastebin"
# This is the "requests" format # This is the "requests" format
if paste_type == 'requests': if paste_type in ['requests', 'curl']:
paste_file = {'file': (paste_title+'.log', log_data)} paste_file = {'file': (paste_title+'.log', log_data)}
if paste_post1: if paste_post1:
paste_file.update(paste_post1) paste_file.update(paste_post1)
@@ -1079,8 +1075,50 @@ def report_send(item, description='', fatal=False):
data = httptools.downloadpage(paste_host, params=paste_params, file=log_data, data = httptools.downloadpage(paste_host, params=paste_params, file=log_data,
file_name=paste_title+'.log', timeout=paste_timeout, file_name=paste_title+'.log', timeout=paste_timeout,
random_headers=paste_random_headers, headers=paste_headers) random_headers=paste_random_headers, headers=paste_headers)
elif paste_type == 'curl':
paste_sufix = '/create_session'
data_post = {'file_size': len(log_data)}
logger.error(data_post)
data = httptools.downloadpage(paste_host+paste_sufix, params=paste_params,
ignore_response_code=True, post=data_post, timeout=paste_timeout, alfa_s=True,
random_headers=paste_random_headers, headers=paste_headers).data
data = jsontools.load(data)
if not data.get("fuid", ""):
logger.error("fuid: %s" % str(data))
raise
fuid = data["fuid"]
paste_sufix = '/chunk'
log_data_chunks = log_data
i = 0
chunk_len = 1024
while len(log_data_chunks) > 0:
i += 1
chunk = log_data_chunks[:chunk_len]
log_data_chunks = log_data_chunks[chunk_len:]
data_post = {'fuid': fuid, 'chunk_index': i}
data = httptools.downloadpage(paste_host+paste_sufix, params=paste_params, file=chunk, alfa_s=True,
ignore_response_code=True, post=data_post, timeout=paste_timeout, CF_test=False,
random_headers=paste_random_headers, headers=paste_headers).data
if not 'successful' in data:
logger.error("successful: %s" % str(data))
raise
data = {}
paste_sufix = '/finalise'
data_post = {'fuid': fuid, 'total_chunks': i, 'file_name': paste_title+'.log', 'file_type': 'doc'}
resp = httptools.downloadpage(paste_host+paste_sufix, params=paste_params,
ignore_response_code=True, post=data_post, timeout=paste_timeout,
random_headers=paste_random_headers, headers=paste_headers)
if not resp.data:
logger.error("resp.content: %s" % str(resp.data))
raise
data['data'] = resp.data
data = type('HTTPResponse', (), data)
except: except:
msg = 'Inténtelo más tarde' msg = 'Try later'
logger.error('Failed to save report. ' + msg) logger.error('Failed to save report. ' + msg)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
continue continue
@@ -1093,16 +1131,20 @@ def report_send(item, description='', fatal=False):
paste_host_return = '' paste_host_return = ''
# Responses to REQUESTS requests # Responses to REQUESTS requests
if paste_type == 'requests': # Response of request type "requests"? if paste_type in ['requests', 'curl']: # Response of request type "requests"?
if paste_resp == 'json': # Answer in JSON format? if paste_resp == 'json': # Answer in JSON format?
if paste_resp_key in data.data: if paste_resp_key in data.data:
if not paste_url: key = jsontools.load(data.data)[paste_resp_key]
key = jsontools.load(data.data)[paste_resp_key] # with a label if paste_url and key: # hay etiquetas adicionales?
else: try:
key = jsontools.load(data.data)[paste_resp_key][paste_url] # with two nested tags for key_part in paste_url.split(','):
item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key, key = key[key_part] # por cada etiqueta adicional
paste_host_return_tail) except:
else: key = ''
if key:
item.url = "%s%s%s" % (paste_host_resp+paste_host_return, key,
paste_host_return_tail)
if not key:
logger.error('ERROR in data return format. data.data=' + str(data.data)) logger.error('ERROR in data return format. data.data=' + str(data.data))
continue continue
+100 -188
View File
@@ -1,36 +1,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
# Search trailers from youtube, filmaffinity, mymovies, vimeo, etc... # Search trailers from tmdb, youtube and mymovies...
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
from __future__ import division from __future__ import division
#from builtins import str
# from builtins import str
import sys import sys
import xbmcaddon from channelselector import get_thumb
PY3 = False PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
from past.utils import old_div
if PY3: if PY3:
#from future import standard_library # from future import standard_library
#standard_library.install_aliases() # standard_library.install_aliases()
import urllib.parse as urllib # It is very slow in PY2. In PY3 it is native import urllib.parse as urllib # It is very slow in PY2. In PY3 it is native
import urllib.parse as urlparse import urllib.parse as urlparse
from concurrent import futures
else: else:
import urllib # We use the native of PY2 which is faster import urllib # We use the native of PY2 which is faster
import urlparse import urlparse
from concurrent_py2 import futures
import re import re
from core import httptools, jsontools, scrapertools, servertools from core import httptools, scrapertools, servertools
from core.support import match, thumb from core.support import match, thumb
from core.item import Item from core.item import Item
from platformcode import config, logger from platformcode import config, logger, launcher
from platformcode import platformtools from platformcode import platformtools
info_language = ["it", "en", "es", "fr", "de", "pt"] # from videolibrary.json info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json
def_lang = info_language[config.get_setting("info_language", "videolibrary")] def_lang = info_language[config.get_setting("info_language", "videolibrary")]
result = None result = None
@@ -44,10 +48,14 @@ else:
def buscartrailer(item, trailers=[]): def buscartrailer(item, trailers=[]):
logger.debug() logger.debug()
if item.contentType != "movie":
tipo = "tv"
else:
tipo = "movie"
# List of actions if run from context menu # List of actions if run from context menu
if item.action == "manual_search" and item.contextual: if item.action == "manual_search" and item.contextual:
itemlist = manual_search(item) itemlist = manual_search(item, tipo)
item.contentTitle = itemlist[0].contentTitle item.contentTitle = itemlist[0].contentTitle
elif 'search' in item.action and item.contextual: elif 'search' in item.action and item.contextual:
itemlist = globals()[item.action](item) itemlist = globals()[item.action](item)
@@ -67,7 +75,8 @@ def buscartrailer(item, trailers=[]):
item.contentTitle = item.contentTitle.strip() item.contentTitle = item.contentTitle.strip()
elif keyboard: elif keyboard:
contentTitle = re.sub(r'\[\/*(B|I|COLOR)\s*[^\]]*\]', '', item.contentTitle.strip()) contentTitle = re.sub(r'\[\/*(B|I|COLOR)\s*[^\]]*\]', '', item.contentTitle.strip())
item.contentTitle = platformtools.dialog_input(default=contentTitle, heading=config.get_localized_string(70505)) item.contentTitle = platformtools.dialog_input(default=contentTitle,
heading=config.get_localized_string(70505))
if item.contentTitle is None: if item.contentTitle is None:
item.contentTitle = contentTitle item.contentTitle = contentTitle
else: else:
@@ -87,32 +96,28 @@ def buscartrailer(item, trailers=[]):
title, url, server = servertools.findvideos(url)[0] title, url, server = servertools.findvideos(url)[0]
title = "Trailer [" + server + "]" title = "Trailer [" + server + "]"
itemlist.append(item.clone(title=title, url=url, server=server, action="play")) itemlist.append(item.clone(title=title, url=url, server=server, action="play"))
if item.show or item.infoLabels['tvshowtitle'] or item.contentType != "movie":
tipo = "tv"
else:
tipo = "movie"
try: try:
if not trailers: for trailer in trailers:
itemlist.extend(tmdb_trailers(item, tipo)) title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en",
else: "ING").replace(
for trailer in trailers: "it", "ITA") + ") [tmdb/youtube]"
title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en", "ING").replace("it", "ITA") + ") [tmdb/youtube]" itemlist.append(item.clone(action="play", title=title, url=trailer['url'], server="youtube"))
itemlist.append(item.clone(action="play", title=title, url=trailer['url'], server="youtube"))
except: except:
import traceback import traceback
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
if item.contextual: title = "%s" multi_search(item, itemlist, tipo)
else: title = "%s" if not itemlist:
itemlist.append(item.clone(title=config.get_localized_string(70501), title2=item.contentTitle,
itemlist.append(item.clone(title=title % config.get_localized_string(70507), action="youtube_search", thumbnail=thumb('search'))) action="", thumbnail=get_thumb('nofolder.png'), text_color=""))
itemlist.append(item.clone(title=title % config.get_localized_string(70508), action="mymovies_search", thumbnail=thumb('search')))
itemlist.append(item.clone(title=title % config.get_localized_string(70024), action="filmaffinity_search", thumbnail=thumb('search')))
from lib.fuzzy_match import algorithims
itemlist.sort(key=lambda r: algorithims.trigram(item.contentTitle + ' trailer', r.title), reverse=True)
if item.contextual: if item.contextual:
global window_select, result global window_select, result
select = Select("DialogSelect.xml", config.get_runtime_path(), item=item, itemlist=itemlist, caption=config.get_localized_string(70506) + item.contentTitle) select = Select("DialogSelect.xml", config.get_runtime_path(), item=item, itemlist=itemlist,
caption=config.get_localized_string(70506) + item.contentTitle)
window_select.append(select) window_select.append(select)
select.doModal() select.doModal()
@@ -121,16 +126,24 @@ def buscartrailer(item, trailers=[]):
return itemlist return itemlist
def manual_search(item): def multi_search(item, itemlist, tipo):
ris = []
with futures.ThreadPoolExecutor() as executor:
ris.append(executor.submit(mymovies_search, item))
ris.append(executor.submit(youtube_search, item))
ris.append(executor.submit(tmdb_trailers, item, tipo))
for r in futures.as_completed(ris):
itemlist.extend(r.result())
def manual_search(item, tipo):
logger.debug() logger.debug()
itemlist = []
texto = platformtools.dialog_input(default=item.contentTitle, heading=config.get_localized_string(30112)) texto = platformtools.dialog_input(default=item.contentTitle, heading=config.get_localized_string(30112))
if texto is not None: if texto is not None:
if item.extra == "mymovies": multi_search(item.clone(contentTitle=texto), itemlist, tipo)
return mymovies_search(item.clone(contentTitle=texto)) return itemlist
elif item.extra == "youtube":
return youtube_search(item.clone(contentTitle=texto, page=""))
elif item.extra == "filmaffinity":
return filmaffinity_search(item.clone(contentTitle=texto, page="", year=""))
def tmdb_trailers(item, tipo="movie"): def tmdb_trailers(item, tipo="movie"):
@@ -145,9 +158,18 @@ def tmdb_trailers(item, tipo="movie"):
tmdb_search = Tmdb(texto_buscado=item.contentTitle, tipo=tipo, year=item.infoLabels['year']) tmdb_search = Tmdb(texto_buscado=item.contentTitle, tipo=tipo, year=item.infoLabels['year'])
if tmdb_search: if tmdb_search:
for result in tmdb_search.get_videos(): for vid in tmdb_search.get_videos():
title = result['name'] + " [" + result['size'] + "p] (" + result['language'].replace("en", "ING").replace("it", "ITA") + ") [tmdb/youtube]" found = False
itemlist.append(item.clone(action="play", title=title, url=result['url'], server="youtube")) if vid['type'].lower() == 'trailer':
title = vid['name']
it = item.clone(action="play", title=title, title2="TMDB(youtube) - " + vid['language'].replace("en", "ING").replace("it", "ITA") + " [" + vid['size'] + "p]", url=vid['url'], server="youtube")
itemlist.append(it)
if vid['language'] == def_lang and not found: # play now because lang is correct and TMDB is trusted
found = True
launcher.run(it)
while platformtools.is_playing():
xbmc.sleep(100)
return itemlist return itemlist
@@ -164,30 +186,25 @@ def youtube_search(item):
else: else:
title = urllib.quote(title) title = urllib.quote(title)
title = title.replace("%20", "+") title = title.replace("%20", "+")
data = httptools.downloadpage("https://www.youtube.com/results?sp=EgIQAQ%253D%253D&q=" + title).data 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'thumbnails":\[\{"url":"(https://i.ytimg.com/vi[^"]+).*?'
patron += r'text":"([^"]+).*?' patron += r'text":"([^"]+).*?'
patron += r'simpleText":"[^"]+.*?simpleText":"([^"]+).*?' patron += r'simpleText":"[^"]+.*?simpleText":"([^"]+).*?'
patron += r'url":"([^"]+)' patron += r'url":"([^"]+)'
matches = scrapertools.find_multiple_matches(data, patron) matches = scrapertools.find_multiple_matches(data, patron)
for scrapedthumbnail, scrapedtitle, scrapedduration, scrapedurl in matches: for scrapedthumbnail, scrapedtitle, scrapedduration, scrapedurl in matches:
scrapedtitle = scrapedtitle if PY3 else scrapedtitle.decode('utf8').encode('utf8') + " (" + scrapedduration + ")" scrapedtitle = scrapedtitle if PY3 else scrapedtitle.decode('utf8').encode('utf8')
if item.contextual: if item.contextual:
scrapedtitle = "%s" % scrapedtitle scrapedtitle = "%s" % scrapedtitle
url = urlparse.urljoin('https://www.youtube.com/', scrapedurl) url = urlparse.urljoin('https://www.youtube.com/', scrapedurl)
itemlist.append(item.clone(title=scrapedtitle, action="play", server="youtube", url=url, thumbnail=scrapedthumbnail)) itemlist.append(item.clone(title=scrapedtitle, title2='Youtube - ' + scrapedduration, action="play", server="youtube",
next_page = scrapertools.find_single_match(data, '<a href="([^"]+)"[^>]+><span class="yt-uix-button-content">') url=url, thumbnail=scrapedthumbnail))
if next_page != "": # next_page = scrapertools.find_single_match(data, '<a href="([^"]+)"[^>]+><span class="yt-uix-button-content">')
next_page = urlparse.urljoin("https://www.youtube.com", next_page) # if next_page != "":
itemlist.append(item.clone(title=config.get_localized_string(30992), action="youtube_search", extra="youtube", page=next_page, thumbnail=thumb('search'), text_color="")) # next_page = urlparse.urljoin("https://www.youtube.com", next_page)
if not itemlist: # itemlist.append(item.clone(title=config.get_localized_string(30992), action="youtube_search", extra="youtube",
itemlist.append(item.clone(title=config.get_localized_string(70501) % title, action="", thumbnail="", text_color="")) # page=next_page, thumbnail=thumb('search'), text_color=""))
if keyboard:
if item.contextual:
title = "%s"
else:
title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70510), action="manual_search", thumbnail=thumb('search'), extra="youtube"))
return itemlist return itemlist
@@ -197,146 +214,48 @@ def mymovies_search(item):
title = item.contentTitle title = item.contentTitle
url = 'https://www.mymovies.it/ricerca/ricerca.php?limit=true&q=' + title url = 'https://www.mymovies.it/ricerca/ricerca.php?limit=true&q=' + title
js = json.loads(httptools.downloadpage(url).data)['risultati']['film']['elenco'] try:
js = json.loads(httptools.downloadpage(url).data)['risultati']['film']['elenco']
except:
return []
itemlist = [] itemlist = []
for it in js: with futures.ThreadPoolExecutor() as executor:
itemlist.append(item.clone(title=it['titolo'], thumbnail=it['immagine'].replace('\\',''), url=it['url'].replace('\\',''), action ='search_links_mymovies')) ris = [executor.submit(search_links_mymovies, item.clone(title=it['titolo'], title2='MYmovies', thumbnail=it['immagine'].replace('\\', ''), url=it['url'].replace('\\', ''))) for it in js]
for r in futures.as_completed(ris):
if not itemlist: if r.result():
itemlist.append(item.clone(title=config.get_localized_string(70501), action="", thumbnail="", text_color="")) itemlist.append(r.result())
if keyboard:
if item.contextual: title = "%s"
else: title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70511), action="manual_search", thumbnail=thumb('search'), extra="mymovies"))
return itemlist return itemlist
def search_links_mymovies(item): def search_links_mymovies(item):
global result
logger.debug() logger.debug()
trailer_url = match(item, patron=r'<li class="bottone_playlist"[^>]+><a href="([^"]+)"').match trailer_url = match(item, patron=r'<source src="([^"]+)').match
itemlist = []
data = httptools.downloadpage(item.url).data
if trailer_url: if trailer_url:
itemlist.append(item.clone(title=config.get_localized_string(60221) + ' ' + item.title, url=trailer_url, server='directo', action="play")) it = item.clone(url=trailer_url, server='directo', action="play")
itemlist = servertools.get_servers_itemlist(itemlist) if 'tmdb_id' in it.infoLabels:
del it.infoLabels['tmdb_id'] # for not saving watch time
else: return it
if keyboard:
if item.contextual:
title = "%s"
else:
title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70513), action="manual_search", thumbnail=thumb('search'), extra="filmaffinity"))
return itemlist
def filmaffinity_search(item):
logger.debug()
if item.filmaffinity:
item.url = item.filmaffinity
return search_links_filmaff(item)
# Check if it is a zero search or comes from the Next option
if item.page != "":
data = httptools.downloadpage(item.page).data
else:
params = urllib.urlencode([('stext', item.contentTitle), ('stype%5B%5D', 'title'), ('country', ''), ('genre', ''), ('fromyear', item.year), ('toyear', item.year)])
url = "http://www.filmaffinity.com/es/advsearch.php?%s" % params
data = httptools.downloadpage(url).data
itemlist = []
patron = '<div class="mc-poster">.*?<img.*?src="([^"]+)".*?' \
'<div class="mc-title"><a href="/es/film(\d+).html"[^>]+>(.*?)<img'
matches = scrapertools.find_multiple_matches(data, patron)
# If there is only one result, search directly for the trailers, but list all the results
if len(matches) == 1:
item.url = "http://www.filmaffinity.com/es/evideos.php?movie_id=%s" % matches[0][1]
item.thumbnail = matches[0][0]
if not item.thumbnail.startswith("http"): item.thumbnail = "http://www.filmaffinity.com" + item.thumbnail
itemlist = search_links_filmaff(item)
elif len(matches) > 1:
for scrapedthumbnail, id, scrapedtitle in matches:
if not scrapedthumbnail.startswith("http"): scrapedthumbnail = "http://www.filmaffinity.com" + scrapedthumbnail
scrapedurl = "http://www.filmaffinity.com/es/evideos.php?movie_id=%s" % id
if PY3: scrapedtitle = unicode(scrapedtitle, encoding="utf-8", errors="ignore")
scrapedtitle = scrapertools.htmlclean(scrapedtitle)
itemlist.append(item.clone(title=scrapedtitle, url=scrapedurl, action="search_links_filmaff", thumbnail=scrapedthumbnail))
next_page = scrapertools.find_single_match(data, '<a href="([^"]+)">&gt;&gt;</a>')
if next_page != "":
next_page = urlparse.urljoin("http://www.filmaffinity.com/es/", next_page)
itemlist.append(item.clone(title=config.get_localized_string(30992), page=next_page, action="filmaffinity_search", thumbnail=thumb('search'), text_color=""))
if not itemlist: itemlist.append(item.clone(title=config.get_localized_string(70501) % item.contentTitle, action="", thumbnail="", text_color=""))
if keyboard:
if item.contextual: title = "%s"
else: title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70513), action="manual_search", thumbnail=thumb('search'), extra="filmaffinity"))
return itemlist
def search_links_filmaff(item):
logger.debug()
itemlist = []
data = httptools.downloadpage(item.url).data
if not '<a class="lnkvvid"' in data:
itemlist.append(item.clone(title=config.get_localized_string(70503), action="", text_color=""))
else:
patron = '<a class="lnkvvid".*?<b>(.*?)</b>.*?iframe.*?src="([^"]+)"'
matches = scrapertools.find_multiple_matches(data, patron)
for scrapedtitle, scrapedurl in matches:
if not scrapedurl.startswith("http:"):
scrapedurl = urlparse.urljoin("http:", scrapedurl)
trailer_url = scrapedurl.replace("-nocookie.com/embed/", ".com/watch?v=")
if "youtube" in trailer_url:
server = "youtube"
code = scrapertools.find_single_match(trailer_url, 'v=([A-z0-9\-_]+)')
thumbnail = "https://img.youtube.com/vi/%s/0.jpg" % code
else:
server = ""
thumbnail = item.thumbnail
if PY3:
scrapedtitle = unicode(scrapedtitle, encoding="utf-8", errors="ignore")
scrapedtitle = scrapertools.htmlclean(scrapedtitle)
scrapedtitle += " [" + server + "]"
if item.contextual:
scrapedtitle = "%s" % scrapedtitle
itemlist.append(item.clone(title=scrapedtitle, url=trailer_url, server=server, action="play", thumbnail=thumbnail))
itemlist = servertools.get_servers_itemlist(itemlist)
if keyboard:
if item.contextual:
title = "%s"
else:
title = "%s"
itemlist.append(item.clone(title=title % config.get_localized_string(70513), action="manual_search", thumbnail="", extra="filmaffinity"))
return itemlist
try: try:
import xbmcgui import xbmcgui
import xbmc import xbmc
class Select(xbmcgui.WindowXMLDialog): class Select(xbmcgui.WindowXMLDialog):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.item = kwargs.get('item') self.item = kwargs.get('item')
self.itemlist = kwargs.get('itemlist') self.itemlist = kwargs.get('itemlist')
self.caption = kwargs.get('caption') self.caption = kwargs.get('caption')
self.result = None
def onInit(self): def onInit(self):
try: try:
self.control_list = self.getControl(6) self.control_list = self.getControl(6)
self.getControl(5).setNavigation(self.control_list, self.control_list, self.control_list, self.control_list) self.getControl(5).setNavigation(self.control_list, self.control_list, self.control_list,
self.control_list)
self.getControl(3).setEnabled(0) self.getControl(3).setEnabled(0)
self.getControl(3).setVisible(0) self.getControl(3).setVisible(0)
except: except:
@@ -347,35 +266,30 @@ try:
except: except:
pass pass
self.getControl(1).setLabel("" + self.caption + "") self.getControl(1).setLabel("" + self.caption + "")
self.getControl(5).setLabel(config.get_localized_string(60495)) if keyboard:
self.getControl(5).setLabel(config.get_localized_string(70510))
self.items = [] self.items = []
for item in self.itemlist: for item in self.itemlist:
item_l = xbmcgui.ListItem(item.title) item_l = xbmcgui.ListItem(item.title, item.title2)
item_l.setArt({'thumb': item.thumbnail}) item_l.setArt({'thumb': item.thumbnail})
item_l.setProperty('item_copy', item.tourl()) item_l.setProperty('item_copy', item.tourl())
self.items.append(item_l) self.items.append(item_l)
self.control_list.reset() self.control_list.reset()
self.control_list.addItems(self.items) self.control_list.addItems(self.items)
self.setFocus(self.control_list) self.setFocus(self.control_list)
def onClick(self, id): def onClick(self, id):
global window_select, result global window_select, result
# Cancel button y [X] # Cancel button y [X]
if id == 7: if id == 7:
window_select[-1].close() window_select[-1].close()
if id == 5: if id == 5 and keyboard:
self.result = "_no_video"
result = "no_video"
self.close() self.close()
window_select.pop() buscartrailer(self.item.clone(action="manual_search", extra="youtube"))
if not window_select:
if not self.item.windowed:
del window_select
else:
window_select[-1].doModal()
def onAction(self, action): def onAction(self, action):
global window_select, result global window_select, result
if action == 92 or action == 110: if action == 92 or action == 110:
self.result = "no_video"
result = "no_video" result = "no_video"
self.close() self.close()
window_select.pop() window_select.pop()
@@ -394,10 +308,8 @@ try:
xbmc.sleep(200) xbmc.sleep(200)
if puede: if puede:
result = video_urls[-1][1] result = video_urls[-1][1]
self.result = video_urls[-1][1]
else: else:
result = None result = None
self.result = None
elif item.action == "play" and not self.item.windowed: elif item.action == "play" and not self.item.windowed:
for window in window_select: for window in window_select:
window.close() window.close()
+2 -1
View File
@@ -417,6 +417,8 @@ def findvideos(item):
all_videolibrary = [] all_videolibrary = []
ch_results = [] ch_results = []
list_servers = []
with futures.ThreadPoolExecutor() as executor: with futures.ThreadPoolExecutor() as executor:
for nom_canal, json_path in list(list_canales.items()): for nom_canal, json_path in list(list_canales.items()):
if filtro_canal and filtro_canal != nom_canal.capitalize(): if filtro_canal and filtro_canal != nom_canal.capitalize():
@@ -476,7 +478,6 @@ def findvideos(item):
del item.library_urls[nom_canal] del item.library_urls[nom_canal]
item_json = Item().fromjson(filetools.read(json_path)) item_json = Item().fromjson(filetools.read(json_path))
list_servers = []
# support.dbg() # support.dbg()
try: from urllib.parse import urlsplit try: from urllib.parse import urlsplit
except ImportError: from urlparse import urlsplit except ImportError: from urlparse import urlsplit
+3 -3
View File
@@ -3,9 +3,9 @@ rm tests/home/userdata/addon_data/plugin.video.kod/settings_servers/*.json
rm tests/home/userdata/addon_data/plugin.video.kod/cookies.dat rm tests/home/userdata/addon_data/plugin.video.kod/cookies.dat
rm tests/home/userdata/addon_data/plugin.video.kod/kod_db.sqlite rm tests/home/userdata/addon_data/plugin.video.kod/kod_db.sqlite
python3 -m pip install --upgrade pip python3 -m pip install --upgrade pip
pip install sakee pip install -U sakee
pip install html-testRunner pip install -U html-testRunner
pip install parameterized pip install -U parameterized
export PYTHONPATH=$PWD export PYTHONPATH=$PWD
export KODI_INTERACTIVE=0 export KODI_INTERACTIVE=0
export KODI_HOME=$PWD/tests/home export KODI_HOME=$PWD/tests/home
+8 -10
View File
@@ -315,6 +315,7 @@ class GenericServerTest(unittest.TestCase):
def test_get_video_url(self): def test_get_video_url(self):
module = __import__('servers.%s' % self.name, fromlist=["servers.%s" % self.name]) module = __import__('servers.%s' % self.name, fromlist=["servers.%s" % self.name])
page_url = self.server.url page_url = self.server.url
httptools.default_headers['Referer'] = self.server.referer
print('testing ' + page_url) print('testing ' + page_url)
print('Found on ' + self.server.foundOn) print('Found on ' + self.server.foundOn)
print() print()
@@ -342,10 +343,10 @@ class GenericServerTest(unittest.TestCase):
print(headers) print(headers)
if 'magnet:?' in directUrl: # check of magnet links not supported if 'magnet:?' in directUrl: # check of magnet links not supported
continue continue
if directUrl.split('.')[-1] == 'm3u8': # m3u8 is a text file and HEAD may be forbidden page = downloadpage(directUrl, headers=headers, only_headers=True, use_requests=True, verify=False)
if not page.success and directUrl.split('.')[-1] == 'm3u8': # m3u8 is a text file and HEAD may be forbidden
page = downloadpage(directUrl, headers=headers, use_requests=True, verify=False) page = downloadpage(directUrl, headers=headers, use_requests=True, verify=False)
else:
page = downloadpage(directUrl, headers=headers, only_headers=True, use_requests=True, verify=False)
self.assertTrue(page.success, self.name + ' scraper returned an invalid link') self.assertTrue(page.success, self.name + ' scraper returned an invalid link')
self.assertLess(page.code, 400, self.name + ' scraper returned a ' + str(page.code) + ' link') self.assertLess(page.code, 400, self.name + ' scraper returned a ' + str(page.code) + ' link')
contentType = page.headers['Content-Type'] contentType = page.headers['Content-Type']
@@ -356,10 +357,7 @@ class GenericServerTest(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
if 'KOD_TST_CH' not in os.environ: unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(report_name='report', add_timestamp=False, combine_reports=True,
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(report_name='report', add_timestamp=False, combine_reports=True, report_title='KoD Test Suite', template=os.path.join(config.get_runtime_path(), 'tests', 'template.html')), exit=False)
report_title='KoD Test Suite', template=os.path.join(config.get_runtime_path(), 'tests', 'template.html')), exit=False) import webbrowser
import webbrowser webbrowser.open(os.path.join(outDir, 'report.html'))
webbrowser.open(os.path.join(outDir, 'report.html'))
else:
unittest.main()