KoD 1.4.1
- ridisegnata la finestra della scelta film/serietv quando si aggiunge in videoteca\n- modifiche minori, qualche fix ai canali/server ed alla ricerca alternativa\n
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.4" provider-name="KoD Team">
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.4.1" provider-name="KoD Team">
|
||||
<requires>
|
||||
<!-- <import addon="script.module.libtorrent" optional="true"/> -->
|
||||
<import addon="metadata.themoviedb.org"/>
|
||||
@@ -26,9 +26,8 @@
|
||||
<screenshot>resources/media/themes/ss/2.png</screenshot>
|
||||
<screenshot>resources/media/themes/ss/3.png</screenshot>
|
||||
</assets>
|
||||
<news>- completato il supporto al futuro Kodi 19
|
||||
- ridisegnato infoplus
|
||||
- fix vari ed eventuali</news>
|
||||
<news>- ridisegnata la finestra della scelta film/serietv quando si aggiunge in videoteca
|
||||
- modifiche minori, qualche fix ai canali/server ed alla ricerca alternativa</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>
|
||||
|
||||
101
channels.json
101
channels.json
@@ -1,48 +1,57 @@
|
||||
{
|
||||
"altadefinizione01": "https://www.altadefinizione01.green",
|
||||
"altadefinizione01_link": "https://altadefinizione01.energy",
|
||||
"altadefinizioneclick": "https://altadefinizione.vote",
|
||||
"animealtadefinizione": "https://www.animealtadefinizione.it",
|
||||
"animeforce": "https://ww1.animeforce.org",
|
||||
"animeleggendari": "https://animeora.com",
|
||||
"animesaturn": "https://www.animesaturn.it",
|
||||
"animestream": "https://www.animeworld.tv",
|
||||
"animesubita": "http://www.animesubita.org",
|
||||
"animetubeita": "http://www.animetubeita.com",
|
||||
"animeunity": "https://www.animeunity.it",
|
||||
"animeuniverse": "https://www.animeuniverse.it/",
|
||||
"animeworld": "https://www.animeworld.tv",
|
||||
"casacinema": "https://www.casacinema.page",
|
||||
"cb01anime": "https://www.cineblog01.red",
|
||||
"cinemalibero": "https://www.cinemalibero.space",
|
||||
"cinetecadibologna": "http://cinestore.cinetecadibologna.it",
|
||||
"dreamsub": "https://dreamsub.stream",
|
||||
"dsda": "https://www.dsda.press",
|
||||
"fastsubita": "https://fastsubita.online",
|
||||
"filmgratis": "https://www.filmaltadefinizione.tv",
|
||||
"filmigratis": "https://filmigratis.org",
|
||||
"filmpertutti": "https://www.filmpertutti.fun",
|
||||
"filmsenzalimiticc": "https://www.filmsenzalimiti01.casa",
|
||||
"filmstreaming01": "https://filmstreaming01.com",
|
||||
"guardaserie_stream": "https://guardaserie.host",
|
||||
"guardaseriecam": "https://guardaserie.cam",
|
||||
"guardaserieclick": "https://www.guardaserie.blue",
|
||||
"guardaserieicu": "https://guardaserie.us",
|
||||
"hd4me": "https://hd4me.net",
|
||||
"ilgeniodellostreaming": "https://ilgeniodellostreaming.fi",
|
||||
"ilgeniodellostreaming_cam": "https://ilgeniodellostreaming.tel",
|
||||
"italiaserie": "https://italiaserie.org",
|
||||
"mondoserietv": "https://mondoserietv.fun",
|
||||
"piratestreaming": "https://www.piratestreaming.buzz",
|
||||
"polpotv": "https://polpotv.life",
|
||||
"raiplay": "https://www.raiplay.it",
|
||||
"seriehd": "https://seriehd.group",
|
||||
"serietvonline": "https://serietvonline.biz",
|
||||
"serietvsubita": "http://serietvsubita.xyz",
|
||||
"serietvu": "https://www.serietvu.link",
|
||||
"streamingcommunity": "https://streamingcommunity.to",
|
||||
"streamtime": "https://t.me/s/StreamTime",
|
||||
"tantifilm": "https://www.tantifilm.tel",
|
||||
"toonitalia": "https://toonitalia.org",
|
||||
"vvvvid": "https://www.vvvvid.it"
|
||||
"findhost": {
|
||||
"altadefinizione01": "https://altadefinizione01-nuovo.info",
|
||||
"altadefinizioneclick": "https://altadefinizione-nuovo.me",
|
||||
"animealtadefinizione": "https://www.animealtadefinizione.it",
|
||||
"cineblog01": "https://cb01.uno",
|
||||
"eurostreaming": "https://eurostreaming.link",
|
||||
"ilcorsaronero": "https://lagazzettadelcorsaro.com",
|
||||
"seriehd": "https://nuovoindirizzo.info/seriehd/",
|
||||
"serietvonline": "https://serietvonline.online",
|
||||
"tantifilm": "https://www.tantifilm.wiki",
|
||||
"film4k": "https://film4k-nuovo.link"
|
||||
},
|
||||
"direct": {
|
||||
"altadefinizione01_link": "https://altadefinizione01.energy",
|
||||
"animealtadefinizione": "https://www.animealtadefinizione.it",
|
||||
"animeforce": "https://ww1.animeforce.org",
|
||||
"animeleggendari": "https://animeora.com",
|
||||
"animesaturn": "https://www.animesaturn.it",
|
||||
"animestream": "https://www.animeworld.tv",
|
||||
"animesubita": "http://www.animesubita.org",
|
||||
"animetubeita": "http://www.animetubeita.com",
|
||||
"animeunity": "https://www.animeunity.it",
|
||||
"animeuniverse": "https://www.animeuniverse.it/",
|
||||
"animeworld": "https://www.animeworld.tv",
|
||||
"casacinema": "https://www.casacinema.page",
|
||||
"cb01anime": "https://www.cineblog01.red",
|
||||
"cinemalibero": "https://www.cinemalibero.space",
|
||||
"cinetecadibologna": "http://cinestore.cinetecadibologna.it",
|
||||
"dreamsub": "https://dreamsub.stream",
|
||||
"dsda": "https://www.dsda.press",
|
||||
"fastsubita": "https://fastsubita.online",
|
||||
"filmgratis": "https://www.filmaltadefinizione.tv",
|
||||
"filmigratis": "https://filmigratis.org",
|
||||
"filmpertutti": "https://www.filmpertutti.fun",
|
||||
"filmsenzalimiticc": "https://www.filmsenzalimiti01.casa",
|
||||
"filmstreaming01": "https://filmstreaming01.com",
|
||||
"guardaserie_stream": "https://guardaserie.host",
|
||||
"guardaseriecam": "https://guardaserie.cam",
|
||||
"guardaserieclick": "https://www.guardaserie.blue",
|
||||
"guardaserieicu": "https://guardaserie.us",
|
||||
"hd4me": "https://hd4me.net",
|
||||
"ilgeniodellostreaming": "https://ilgeniodellostreaming.fi",
|
||||
"ilgeniodellostreaming_cam": "https://ilgeniodellostreaming.tel",
|
||||
"italiaserie": "https://italiaserie.org",
|
||||
"mondoserietv": "https://mondoserietv.fun",
|
||||
"piratestreaming": "https://www.piratestreaming.buzz",
|
||||
"polpotv": "https://polpotv.life",
|
||||
"raiplay": "https://www.raiplay.it",
|
||||
"serietvsubita": "http://serietvsubita.xyz",
|
||||
"serietvu": "https://www.serietvu.link",
|
||||
"streamingcommunity": "https://streamingcommunity.to",
|
||||
"streamtime": "https://t.me/s/StreamTime",
|
||||
"toonitalia": "https://toonitalia.org",
|
||||
"vvvvid": "https://www.vvvvid.it"
|
||||
}
|
||||
}
|
||||
@@ -54,18 +54,17 @@ from core.item import Item # per newest
|
||||
|
||||
# se il sito ha un link per ottenere l'url corretto in caso di oscuramenti
|
||||
# la funzione deve ritornare l'indirizzo corretto, verrà chiamata solo se necessario (link primario irraggiungibile)
|
||||
def findhost():
|
||||
def findhost():
|
||||
permUrl = httptools.downloadpage('https://www.cb01.uno/', follow_redirects=False).headers
|
||||
def findhost(url):
|
||||
permUrl = httptools.downloadpage(url, follow_redirects=False).headers
|
||||
if 'google' in permUrl['location']:
|
||||
host = permUrl['location'].replace('https://www.google.it/search?q=site:', '')
|
||||
else:
|
||||
host = permUrl['location']
|
||||
return host
|
||||
|
||||
# se si usa findhost
|
||||
# se si usa findhost metti in channels.json l'url del sito che contiene sempre l'ultimo dominio
|
||||
host = config.get_channel_url(findhost)
|
||||
# se non si usa (metti l'url in channels.json)
|
||||
# se non si usa metti direttamente l'url finale in channels.json
|
||||
host = config.get_channel_url()
|
||||
headers = [['Referer', host]]
|
||||
|
||||
|
||||
@@ -17,10 +17,9 @@ from core import scrapertools, httptools, support
|
||||
from core.item import Item
|
||||
from platformcode import config, logger
|
||||
|
||||
#impostati dinamicamente da findhost()
|
||||
|
||||
def findhost():
|
||||
data = httptools.downloadpage('https://altadefinizione01-nuovo.info/').data
|
||||
def findhost(url):
|
||||
data = httptools.downloadpage(url).data
|
||||
host = scrapertools.find_single_match(data, '<div class="elementor-button-wrapper"> <a href="([^"]+)"')
|
||||
return host
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ from core import support
|
||||
from core.item import Item
|
||||
from platformcode import config
|
||||
|
||||
def findhost():
|
||||
data = support.httptools.downloadpage('https://altadefinizione-nuovo.me/').data
|
||||
def findhost(url):
|
||||
data = support.httptools.downloadpage(url).data
|
||||
host = support.scrapertools.find_single_match(data, '<div class="elementor-button-wrapper"> <a href="([^"]+)"')
|
||||
return host
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ from lib import unshortenit
|
||||
from platformcode import logger, config
|
||||
|
||||
|
||||
def findhost():
|
||||
host = httptools.downloadpage('https://cb01.uno/', follow_redirect=True).url
|
||||
def findhost(url):
|
||||
host = httptools.downloadpage(url, follow_redirect=True).url
|
||||
if host == 'https://cb01.uno/':
|
||||
host = support.match(host, patron=r'<a href="([^"]+)', debug=True).match
|
||||
return host
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"active": true,
|
||||
"thumbnail": "cinemalibero.png",
|
||||
"banner": "cinemalibero.png",
|
||||
"categories": ["movie","tvshow"],
|
||||
"categories": ["movie","tvshow","anime"],
|
||||
"not_active": ["include_in_newest_anime", "include_in_newest_peliculas"],
|
||||
"settings": []
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ from platformcode import config
|
||||
|
||||
|
||||
# rimanda a .today che contiene tutti link a .plus
|
||||
# def findhost():
|
||||
# def findhost(url):
|
||||
# permUrl = httptools.downloadpage('https://www.cinemalibero.online/', follow_redirects=False).headers
|
||||
# try:
|
||||
# import urlparse
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
from core import httptools, support
|
||||
from core.item import Item
|
||||
|
||||
def findhost():
|
||||
permUrl = httptools.downloadpage('https://eurostreaming.link/', follow_redirects=False, only_headers=True).headers
|
||||
def findhost(url):
|
||||
permUrl = httptools.downloadpage(url, follow_redirects=False, only_headers=True).headers
|
||||
host = 'https://'+permUrl['location'].replace('https://www.google.it/search?q=site:', '')
|
||||
return host
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ from core import support
|
||||
from platformcode import logger, config
|
||||
|
||||
|
||||
def findhost():
|
||||
return support.httptools.downloadpage('https://film4k-nuovo.link').url
|
||||
def findhost(url):
|
||||
return support.httptools.downloadpage(url).url
|
||||
|
||||
host = config.get_channel_url(findhost)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from core import httptools, support
|
||||
from core.item import Item
|
||||
from platformcode import config
|
||||
|
||||
# def findhost():
|
||||
# def findhost(url):
|
||||
# page = httptools.downloadpage("https://filmpertutti.nuovo.live/").data
|
||||
# url = scrapertools.find_single_match(page, 'Il nuovo indirizzo di FILMPERTUTTI è <a href="([^"]+)')
|
||||
# return url
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from core import support
|
||||
|
||||
def findhost():
|
||||
data = support.httptools.downloadpage('https://lagazzettadelcorsaro.com/').data
|
||||
def findhost(url):
|
||||
data = support.httptools.downloadpage(url).data
|
||||
url = support.scrapertools.find_single_match(data, '<li><a href="([^"]+)')
|
||||
return url[:-1] if url.endswith('/') else url
|
||||
|
||||
|
||||
@@ -4,17 +4,9 @@
|
||||
# ------------------------------------------------------------
|
||||
|
||||
from core import support
|
||||
from core.item import Item
|
||||
from platformcode import config
|
||||
from xml.dom import minidom
|
||||
|
||||
#impostati dinamicamente da findhost()
|
||||
|
||||
|
||||
host = 'https://metalvideo.com'
|
||||
headers={'X-Requested-With': 'XMLHttpRequest'}
|
||||
|
||||
|
||||
headers = {'X-Requested-With': 'XMLHttpRequest'}
|
||||
|
||||
|
||||
@support.scrape
|
||||
|
||||
@@ -7,7 +7,7 @@ from core import support
|
||||
from core.item import Item
|
||||
from platformcode import logger, config
|
||||
|
||||
# def findhost():
|
||||
# def findhost(url):
|
||||
# return 'https://' + support.match('https://netfreex.uno/', patron='value="site:([^"]+)"').match
|
||||
|
||||
host = config.get_channel_url()
|
||||
|
||||
@@ -7,15 +7,13 @@
|
||||
from core import support, jsontools
|
||||
from core.item import Item
|
||||
from platformcode import config
|
||||
import json, datetime
|
||||
import datetime
|
||||
|
||||
host = config.get_channel_url()
|
||||
|
||||
headers = [['Accept', 'application/ld+json']]
|
||||
|
||||
|
||||
|
||||
|
||||
@support.menu
|
||||
def mainlist(item):
|
||||
# menu = [
|
||||
@@ -57,8 +55,9 @@ def peliculas(item):
|
||||
item.contentType='movie'
|
||||
else:
|
||||
item.contentType='tvshow'
|
||||
itemlist.extend(get_itemlist_element(element, item))
|
||||
itemlist.append(get_itemlist_element(element, item))
|
||||
|
||||
support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
|
||||
try:
|
||||
if support.inspect.stack()[1][3] not in ['newest']:
|
||||
support.nextPage(itemlist, item, next_page=json_object['hydra:view']['hydra:next'])
|
||||
@@ -106,13 +105,14 @@ def search(item, texto):
|
||||
json_object = jsontools.load(data)
|
||||
for movie in json_object['hydra:member']:
|
||||
item.contentType='movie'
|
||||
itemlist.extend(get_itemlist_element(movie,item))
|
||||
itemlist.append(get_itemlist_element(movie,item))
|
||||
item.url = host + "/api/shows?originalTitle="+texto+"&translations.name=" +texto
|
||||
data = support.match(item.url, headers=headers).data
|
||||
json_object = jsontools.load(data)
|
||||
for tvshow in json_object['hydra:member']:
|
||||
item.contentType='tvshow'
|
||||
itemlist.extend(get_itemlist_element(tvshow,item))
|
||||
itemlist.append(get_itemlist_element(tvshow,item))
|
||||
support.tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
|
||||
return itemlist
|
||||
# Continua la ricerca in caso di errore
|
||||
except:
|
||||
@@ -121,6 +121,7 @@ def search(item, texto):
|
||||
support.logger.error("%s" % line)
|
||||
return []
|
||||
|
||||
|
||||
def search_movie_by_genre(item):
|
||||
support.info()
|
||||
itemlist = []
|
||||
@@ -134,6 +135,7 @@ def search_movie_by_genre(item):
|
||||
url="%s/api/movies?genres.id=%s" %(host,genre['id'])))
|
||||
return support.thumb(itemlist, True)
|
||||
|
||||
|
||||
def search_movie_by_year(item):
|
||||
support.info()
|
||||
now = datetime.datetime.now()
|
||||
@@ -149,6 +151,7 @@ def search_movie_by_year(item):
|
||||
action="peliculas"))
|
||||
return itemlist
|
||||
|
||||
|
||||
def findvideos(item):
|
||||
support.info()
|
||||
itemlist = []
|
||||
@@ -170,9 +173,9 @@ def findvideos(item):
|
||||
pass
|
||||
return support.server(item, itemlist=itemlist)
|
||||
|
||||
|
||||
def get_itemlist_element(element,item):
|
||||
support.info()
|
||||
itemlist=[]
|
||||
contentSerieName = ''
|
||||
contentTitle =''
|
||||
try:
|
||||
@@ -189,13 +192,13 @@ def get_itemlist_element(element,item):
|
||||
except:
|
||||
scrapedplot = ""
|
||||
try:
|
||||
scrapedthumbnail="http://"+element['posterPath']
|
||||
scrapedthumbnail="https:"+element['bestPosters'].values()[0]
|
||||
except:
|
||||
scrapedthumbnail=""
|
||||
try:
|
||||
scrapedfanart="http://"+element['backdropPath']
|
||||
except:
|
||||
scrapedfanart=""
|
||||
# try:
|
||||
# scrapedfanart="http:"+element['backdropPath']
|
||||
# except:
|
||||
# scrapedfanart=""
|
||||
|
||||
infoLabels = {}
|
||||
if item.contentType=='movie':
|
||||
@@ -210,20 +213,15 @@ def get_itemlist_element(element,item):
|
||||
quality=''
|
||||
url="%s%s"
|
||||
|
||||
if item.contentType=='movie':
|
||||
support.tmdb.set_infoLabels_itemlist(itemlist)
|
||||
itemlist.append(
|
||||
item.clone(action=next_action,
|
||||
return item.clone(action=next_action,
|
||||
title=support.typo(scrapedtitle, 'bold') + quality,
|
||||
fulltitle=scrapedtitle,
|
||||
show=scrapedtitle,
|
||||
plot=scrapedplot,
|
||||
fanart=scrapedfanart,
|
||||
# fanart=scrapedfanart,
|
||||
thumbnail=scrapedthumbnail,
|
||||
contentTitle=contentTitle,
|
||||
contentSerieName=contentSerieName,
|
||||
contentType=item.contentType,
|
||||
url=url % (host, element['@id']),
|
||||
infoLabels=infoLabels))
|
||||
|
||||
return itemlist
|
||||
infoLabels=infoLabels)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
|
||||
from core import support
|
||||
def findhost():
|
||||
return support.match('https://nuovoindirizzo.info/seriehd/', patron=r'<h2[^>]+><a href="([^"]+)"').match
|
||||
def findhost(url):
|
||||
return support.match(url, patron=r'<h2[^>]+><a href="([^"]+)"').match
|
||||
|
||||
host = support.config.get_channel_url(findhost)
|
||||
headers = [['Referer', host]]
|
||||
@@ -31,7 +31,7 @@ def search(item, texto):
|
||||
|
||||
|
||||
item.contentType = 'tvshow'
|
||||
item.url = host + "/?s=" + texto
|
||||
item.url = host + "/search/" + texto
|
||||
try:
|
||||
return peliculas(item)
|
||||
# Continua la ricerca in caso di errore .
|
||||
|
||||
@@ -21,8 +21,8 @@ from platformcode import config
|
||||
from core.item import Item
|
||||
|
||||
|
||||
def findhost():
|
||||
host = support.match('https://serietvonline.online', patron=r'href="([^"]+)">\s*cliccando qui').matches[-1]
|
||||
def findhost(url):
|
||||
host = support.match(url, patron=r'href="([^"]+)">\s*cliccando qui').matches[-1]
|
||||
return host
|
||||
|
||||
host = config.get_channel_url(findhost)
|
||||
|
||||
@@ -13,8 +13,8 @@ else:
|
||||
from urllib import unquote
|
||||
|
||||
|
||||
def findhost():
|
||||
data = httptools.downloadpage('https://www.popcornstream-nuovo-indirizzo.online/').data
|
||||
def findhost(url):
|
||||
data = httptools.downloadpage(url).data
|
||||
return support.scrapertools.find_single_match(data, '<a href="([^"]+)')
|
||||
|
||||
host = config.get_channel_url(findhost)
|
||||
|
||||
@@ -12,8 +12,8 @@ from platformcode import logger
|
||||
from platformcode import config, unify
|
||||
|
||||
|
||||
def findhost():
|
||||
permUrl = httptools.downloadpage('https://www.tantifilm.wiki/').data
|
||||
def findhost(url):
|
||||
permUrl = httptools.downloadpage(url).data
|
||||
host = scrapertools.find_single_match(permUrl, r'Nuovo indirizzo: <a href="([^"]+)')
|
||||
return host
|
||||
|
||||
|
||||
@@ -4,18 +4,11 @@
|
||||
# ------------------------------------------------------------
|
||||
|
||||
from core import support
|
||||
from core.item import Item
|
||||
from platformcode import config
|
||||
from xml.dom import minidom
|
||||
|
||||
#impostati dinamicamente da findhost()
|
||||
|
||||
|
||||
host = 'http://api.radiotime.com'
|
||||
headers = [['Referer', host]]
|
||||
|
||||
|
||||
|
||||
@support.scrape
|
||||
def mainlist(item):
|
||||
item.url = host
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import urllib
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
|
||||
from core import jsontools
|
||||
from core import jsontools, httptools
|
||||
from core.item import Item
|
||||
from platformcode import logger
|
||||
from platformcode import config
|
||||
|
||||
CHANNELNAME = "youtube_channel"
|
||||
YOUTUBE_V3_API_KEY = "AIzaSyCjsmBT0JZy1RT-PLwB-Zkfba87sa2inyI"
|
||||
|
||||
@@ -11,13 +11,15 @@ try:
|
||||
except ImportError:
|
||||
import urllib, urlparse, cookielib
|
||||
|
||||
|
||||
import os, time, json
|
||||
from threading import Lock
|
||||
from core.jsontools import to_utf8
|
||||
from platformcode import config, logger
|
||||
from core import scrapertools
|
||||
|
||||
# to surpress InsecureRequestWarning
|
||||
import urllib3
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
# Get the addon version
|
||||
__version = config.get_addon_version()
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ def color(text, color):
|
||||
|
||||
def search(channel, item, texto):
|
||||
info(item.url + " search " + texto)
|
||||
if 'findhost' in dir(channel): channel.findhost()
|
||||
item.url = channel.host + "/?s=" + texto
|
||||
try:
|
||||
return channel.peliculas(item)
|
||||
@@ -318,7 +317,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
longtitle += s + parsedTitle.get('episode_title')
|
||||
item.contentEpisodeTitle = parsedTitle.get('episode_title')
|
||||
except:
|
||||
logger.debug('Error')
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
longtitle = typo(longtitle, 'bold')
|
||||
lang1, longtitle = scrapeLang(scraped, lang, longtitle)
|
||||
@@ -479,10 +479,10 @@ def scrape(func):
|
||||
# if url may be changed and channel has findhost to update
|
||||
if 'findhost' in func.__globals__ and not itemlist:
|
||||
info('running findhost ' + func.__module__)
|
||||
host = func.__globals__['findhost']()
|
||||
ch = func.__module__.split('.')[-1]
|
||||
host = config.get_channel_url(func.__globals__['findhost'], ch, True)
|
||||
|
||||
parse = list(urlparse.urlparse(item.url))
|
||||
from core import jsontools
|
||||
jsontools.update_node(host, func.__module__.split('.')[-1], 'url')
|
||||
parse[1] = scrapertools.get_domain_from_url(host)
|
||||
item.url = urlparse.urlunparse(parse)
|
||||
data = None
|
||||
@@ -491,6 +491,9 @@ def scrape(func):
|
||||
else:
|
||||
break
|
||||
|
||||
if action != 'play' and function != 'episodios' and 'patronMenu' not in args and item.contentType in ['movie', 'tvshow', 'episode', 'undefined'] and not disabletmdb:
|
||||
tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
|
||||
|
||||
if (pagination and len(matches) <= pag * pagination) or not pagination: # next page with pagination
|
||||
if patronNext and inspect.stack()[1][3] not in ['newest']:
|
||||
nextPage(itemlist, item, data, patronNext, function)
|
||||
@@ -509,8 +512,6 @@ def scrape(func):
|
||||
args=item.args,
|
||||
page=pag + 1,
|
||||
thumbnail=thumb()))
|
||||
if action != 'play' and function != 'episodios' and 'patronMenu' not in args and item.contentType in ['movie', 'tvshow', 'episode', 'undefined'] and not disabletmdb:
|
||||
tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
|
||||
|
||||
if anime:
|
||||
from platformcode import autorenumber
|
||||
|
||||
10
core/tmdb.py
10
core/tmdb.py
@@ -92,7 +92,7 @@ def cache_response(fn):
|
||||
# import time
|
||||
# start_time = time.time()
|
||||
|
||||
def wrapper(*args):
|
||||
def wrapper(*args, **kwargs):
|
||||
import base64
|
||||
|
||||
def check_expired(ts):
|
||||
@@ -143,7 +143,8 @@ def cache_response(fn):
|
||||
try:
|
||||
|
||||
# cache is not active
|
||||
if not config.get_setting("tmdb_cache", default=False):
|
||||
if not config.get_setting("tmdb_cache", default=False) or not kwargs.get('cache', True):
|
||||
logger.debug('no cache')
|
||||
result = fn(*args)
|
||||
else:
|
||||
|
||||
@@ -861,8 +862,7 @@ class Tmdb(object):
|
||||
|
||||
@staticmethod
|
||||
@cache_response
|
||||
def get_json(url):
|
||||
|
||||
def get_json(url, cache=True):
|
||||
try:
|
||||
result = httptools.downloadpage(url, cookies=False, ignore_response_code=True)
|
||||
|
||||
@@ -1045,7 +1045,7 @@ class Tmdb(object):
|
||||
% (type_search, "&".join(params)))
|
||||
|
||||
logger.info("[Tmdb.py] Searcing %s:\n%s" % (type_search, url))
|
||||
resultado = self.get_json(url)
|
||||
resultado = self.get_json(url, cache=False)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@ import os
|
||||
import sys
|
||||
|
||||
import xbmc
|
||||
|
||||
# on kodi 18 its xbmc.translatePath, on 19 xbmcvfs.translatePath
|
||||
try:
|
||||
import xbmcvfs
|
||||
xbmc.translatePath = xbmcvfs.translatePath
|
||||
except:
|
||||
pass
|
||||
from platformcode import config, logger
|
||||
|
||||
logger.info("init...")
|
||||
|
||||
@@ -24,7 +24,7 @@ else:
|
||||
_urlopen = urllib2.urlopen
|
||||
_Request = urllib2.Request
|
||||
|
||||
def query(name, type='A', server=DOH_SERVER, path="/dns-query", fallback=True,):
|
||||
def query(name, type='A', server=DOH_SERVER, path="/dns-query", fallback=True):
|
||||
"""
|
||||
Returns domain name query results retrieved by using DNS over HTTPS protocol
|
||||
# Reference: https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/
|
||||
|
||||
@@ -544,8 +544,7 @@ class UnshortenIt(object):
|
||||
if uri == prev_uri:
|
||||
logger.info('Use Cloudscraper')
|
||||
uri = httptools.downloadpage(uri, timeout=self._timeout, headers=headers, follow_redirects=False, cf=True).headers['location']
|
||||
# from core import support
|
||||
# support.dbg()
|
||||
|
||||
if "snip." in uri:
|
||||
if 'out_generator' in uri:
|
||||
uri = re.findall('url=(.*)$', uri)[0]
|
||||
|
||||
@@ -72,7 +72,6 @@ def import_videolibrary(item):
|
||||
if config.is_xbmc() and config.get_setting("videolibrary_kodi"):
|
||||
xbmc_videolibrary.clean()
|
||||
p_dialog.update(30)
|
||||
xbmc.sleep(1000)
|
||||
shutil.rmtree(videolibrary_movies_path)
|
||||
shutil.rmtree(videolibrary_tvshows_path)
|
||||
p_dialog.update(50)
|
||||
@@ -102,7 +101,7 @@ def zip(dir, file):
|
||||
temp = file
|
||||
file = filetools.join(temp_path, os.path.split(file)[-1])
|
||||
smb = True
|
||||
with ZipFile(file, "w") as zf:
|
||||
with ZipFile(filetools.file_open(file, 'wb', vfs=False), "w") as zf:
|
||||
abs_src = os.path.abspath(dir)
|
||||
for dirname, subdirs, files in os.walk(dir):
|
||||
for filename in files:
|
||||
@@ -119,5 +118,5 @@ def unzip(dir, file):
|
||||
filetools.copy(file, temp)
|
||||
file = temp
|
||||
|
||||
with ZipFile(file, 'r') as zf:
|
||||
zf.extractall(dir)
|
||||
with ZipFile(filetools.file_open(file, 'rb', vfs=False), 'r') as zf:
|
||||
zf.extractall(dir)
|
||||
|
||||
@@ -258,10 +258,10 @@ def check_channels(inutile=''):
|
||||
|
||||
risultato = {}
|
||||
|
||||
for chann, host in sorted(data.items()):
|
||||
for chann, host in sorted(data['direct'].items()):
|
||||
|
||||
ris = []
|
||||
# to get an idea of the timing
|
||||
# to get an idea of the timing
|
||||
# useful only if you control all channels
|
||||
# for channels with error 522 about 40 seconds are lost ...
|
||||
logger.info("check #### INIZIO #### channel - host :%s - %s " % (chann, host))
|
||||
@@ -290,6 +290,7 @@ def check_channels(inutile=''):
|
||||
|
||||
logger.info("check #### FINE #### rslt :%s " % (rslt))
|
||||
|
||||
risultato = {'findhost': data['findhost'], 'direct': risultato}
|
||||
fileJson_test = 'channels-test.json'
|
||||
# I write the updated file
|
||||
with open(folderJson+'/'+fileJson_test, 'w') as f:
|
||||
|
||||
@@ -15,7 +15,7 @@ __language__ = __settings__.getLocalizedString
|
||||
__version_fix = None
|
||||
__dev_mode = None
|
||||
|
||||
channels_data = list()
|
||||
channels_data = dict()
|
||||
|
||||
def get_addon_core():
|
||||
return __settings__
|
||||
@@ -101,27 +101,29 @@ def is_xbmc():
|
||||
def get_videolibrary_support():
|
||||
return True
|
||||
|
||||
def get_channel_url(findhostMethod=None, name=None):
|
||||
|
||||
def get_channel_url(findhostMethod=None, name=None, forceFindhost=False):
|
||||
from core import jsontools
|
||||
import inspect
|
||||
|
||||
LOCAL_FILE = os.path.join(get_runtime_path(), "channels.json")
|
||||
global channels_data
|
||||
if not channels_data:
|
||||
with open(LOCAL_FILE) as f:
|
||||
channels_data = jsontools.load(f.read())
|
||||
|
||||
frame = inspect.stack()[1]
|
||||
if not name:
|
||||
name = os.path.basename(frame[0].f_code.co_filename).replace('.py', '')
|
||||
if findhostMethod:
|
||||
url = jsontools.get_node_from_file(name, 'url')
|
||||
if not url or 'web.archive.org' in url: # per eliminare tutti i webarchive salvati causa bug httptools CF, eliminare in futuro
|
||||
url = findhostMethod()
|
||||
if not url or 'web.archive.org' in url or forceFindhost: # per eliminare tutti i webarchive salvati causa bug httptools CF, eliminare in futuro
|
||||
url = findhostMethod(channels_data['findhost'][name])
|
||||
jsontools.update_node(url, name, 'url')
|
||||
return url
|
||||
else:
|
||||
ROOT_DIR = xbmc.translatePath(__settings__.getAddonInfo('Path'))
|
||||
LOCAL_FILE = os.path.join(ROOT_DIR, "channels.json")
|
||||
global channels_data
|
||||
if not channels_data:
|
||||
with open(LOCAL_FILE) as f:
|
||||
channels_data = jsontools.load(f.read())
|
||||
return channels_data[name]
|
||||
return channels_data['direct'][name]
|
||||
|
||||
|
||||
def get_system_platform():
|
||||
""" function: to recover the platform that xbmc is running """
|
||||
@@ -147,7 +149,7 @@ def is_autorun_enabled():
|
||||
|
||||
|
||||
def enable_disable_autorun(is_enabled):
|
||||
# using autoexec.py and not service.py to force autorun
|
||||
# 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'
|
||||
@@ -163,7 +165,7 @@ def enable_disable_autorun(is_enabled):
|
||||
file.close()
|
||||
with open(path, "w") as file:
|
||||
file.write(new_content)
|
||||
set_setting('autostart', 'Off')
|
||||
set_setting('autostart', True)
|
||||
return True
|
||||
|
||||
def get_all_settings_addon():
|
||||
|
||||
@@ -6,6 +6,15 @@ from __future__ import unicode_literals
|
||||
import inspect, os, xbmc, sys
|
||||
from platformcode import config
|
||||
|
||||
# for test suite
|
||||
try:
|
||||
xbmc.KodiStub()
|
||||
testMode = True
|
||||
record = False
|
||||
recordedLog = ''
|
||||
import html
|
||||
except:
|
||||
testMode = False
|
||||
LOG_FORMAT = '{addname}[{filename}.{function}:{line}]{sep} {message}'
|
||||
DEBUG_ENABLED = config.get_setting("debug")
|
||||
DEF_LEVEL = xbmc.LOGINFO if sys.version_info[0] >= 3 else xbmc.LOGNOTICE
|
||||
@@ -28,6 +37,10 @@ def error(*args):
|
||||
def log(*args, **kwargs):
|
||||
msg = ''
|
||||
for arg in args: msg += ' ' + str(arg)
|
||||
if testMode and record:
|
||||
global recordedLog
|
||||
recordedLog += msg + '\n'
|
||||
return
|
||||
frame = inspect.currentframe().f_back.f_back
|
||||
filename = frame.f_code.co_filename
|
||||
filename = os.path.basename(filename).split('.')[0]
|
||||
|
||||
@@ -111,6 +111,70 @@ def dialog_browse(_type, heading, shares="files", mask="", useThumbs=False, trea
|
||||
|
||||
|
||||
def dialog_register(heading, user=False, email=False, password=False, user_default='', email_default='', password_default='', captcha_img=''):
|
||||
class Register(xbmcgui.WindowXMLDialog):
|
||||
def Start(self, heading, user, email, password, user_default, email_default, password_default, captcha_img):
|
||||
self.result = {}
|
||||
self.heading = heading
|
||||
self.user = user
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.user_default = user_default
|
||||
self.email_default = email_default
|
||||
self.password_default = password_default
|
||||
self.captcha_img = captcha_img
|
||||
self.doModal()
|
||||
|
||||
return self.result
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mensaje = kwargs.get("mensaje")
|
||||
self.imagen = kwargs.get("imagen")
|
||||
|
||||
def onInit(self):
|
||||
#### Kodi 18 compatibility ####
|
||||
if config.get_platform(True)['num_version'] < 18:
|
||||
self.setCoordinateResolution(2)
|
||||
height = 90
|
||||
self.getControl(10002).setText(self.heading)
|
||||
if self.user:
|
||||
self.getControl(10003).setText(self.user_default)
|
||||
height += 70
|
||||
else:
|
||||
self.getControl(10003).setVisible(False)
|
||||
if self.email:
|
||||
self.getControl(10004).setText(self.email_default)
|
||||
height += 70
|
||||
else:
|
||||
self.getControl(10004).setVisible(False)
|
||||
if self.password:
|
||||
self.getControl(10005).setText(self.password_default)
|
||||
height += 70
|
||||
else:
|
||||
self.getControl(10005).setVisible(False)
|
||||
if self.captcha_img:
|
||||
|
||||
self.getControl(10007).setImage(self.captcha_img)
|
||||
height += 240
|
||||
else:
|
||||
self.getControl(10005).setVisible(False)
|
||||
height += 40
|
||||
if height < 250: height = 250
|
||||
self.getControl(10000).setHeight(height)
|
||||
self.getControl(10001).setHeight(height)
|
||||
self.getControl(10000).setPosition(255, (720 - height) / 2)
|
||||
self.setFocusId(30000)
|
||||
|
||||
def onClick(self, control):
|
||||
if control in [10010]:
|
||||
self.close()
|
||||
|
||||
elif control in [10009]:
|
||||
if self.user: self.result['user'] = self.getControl(10003).getText()
|
||||
if self.email: self.result['email'] = self.getControl(10004).getText()
|
||||
if self.password: self.result['password'] = self.getControl(10005).getText()
|
||||
if self.captcha_img: self.result['captcha'] = self.getControl(10006).getText()
|
||||
self.close()
|
||||
|
||||
dialog = Register('Register.xml', config.get_runtime_path()).Start(heading, user, email, password, user_default, email_default, password_default, captcha_img)
|
||||
return dialog
|
||||
|
||||
@@ -1274,68 +1338,3 @@ def get_platform():
|
||||
ret["arch"] = "arm"
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class Register(xbmcgui.WindowXMLDialog):
|
||||
def Start(self, heading, user, email, password, user_default, email_default, password_default, captcha_img):
|
||||
self.result = {}
|
||||
self.heading = heading
|
||||
self.user = user
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.user_default = user_default
|
||||
self.email_default = email_default
|
||||
self.password_default = password_default
|
||||
self.captcha_img = captcha_img
|
||||
self.doModal()
|
||||
|
||||
return self.result
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mensaje = kwargs.get("mensaje")
|
||||
self.imagen = kwargs.get("imagen")
|
||||
|
||||
def onInit(self):
|
||||
#### Kodi 18 compatibility ####
|
||||
if config.get_platform(True)['num_version'] < 18:
|
||||
self.setCoordinateResolution(2)
|
||||
height = 90
|
||||
self.getControl(10002).setText(self.heading)
|
||||
if self.user:
|
||||
self.getControl(10003).setText(self.user_default)
|
||||
height+=70
|
||||
else:
|
||||
self.getControl(10003).setVisible(False)
|
||||
if self.email:
|
||||
self.getControl(10004).setText(self.email_default)
|
||||
height+=70
|
||||
else:
|
||||
self.getControl(10004).setVisible(False)
|
||||
if self.password:
|
||||
self.getControl(10005).setText(self.password_default)
|
||||
height+=70
|
||||
else:
|
||||
self.getControl(10005).setVisible(False)
|
||||
if self.captcha_img:
|
||||
|
||||
self.getControl(10007).setImage(self.captcha_img)
|
||||
height+=240
|
||||
else:
|
||||
self.getControl(10005).setVisible(False)
|
||||
height +=40
|
||||
if height < 250: height = 250
|
||||
self.getControl(10000).setHeight(height)
|
||||
self.getControl(10001).setHeight(height)
|
||||
self.getControl(10000).setPosition(255, (720-height)/2)
|
||||
self.setFocusId(30000)
|
||||
|
||||
def onClick(self, control):
|
||||
if control in [10010]:
|
||||
self.close()
|
||||
|
||||
elif control in [10009]:
|
||||
if self.user: self.result['user'] = self.getControl(10003).getText()
|
||||
if self.email: self.result['email'] = self.getControl(10004).getText()
|
||||
if self.password: self.result['password'] = self.getControl(10005).getText()
|
||||
if self.captcha_img: self.result['captcha'] = self.getControl(10006).getText()
|
||||
self.close()
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from platformcode import logger, side_menu
|
||||
from platformcode import logger
|
||||
|
||||
|
||||
def context():
|
||||
@@ -18,6 +18,7 @@ def context():
|
||||
return context
|
||||
|
||||
def Side_menu(item):
|
||||
from platformcode import side_menu
|
||||
side_menu.open_menu(item)
|
||||
|
||||
def shortcut_menu(item):
|
||||
|
||||
@@ -161,8 +161,12 @@ def check(background=False):
|
||||
if addon.getSetting("addon_update_message"):
|
||||
if background:
|
||||
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(80040) % commits[0]['sha'][:7], time=3000, sound=False)
|
||||
with open(xbmc.translatePath(changelogFile), 'a+') as fileC:
|
||||
fileC.write(changelog)
|
||||
try:
|
||||
with open(xbmc.translatePath(changelogFile), 'a+') as fileC:
|
||||
fileC.write(changelog)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
elif changelog:
|
||||
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80041) + changelog)
|
||||
else:
|
||||
@@ -175,7 +179,8 @@ def showSavedChangelog():
|
||||
try:
|
||||
with open(xbmc.translatePath(changelogFile), 'r') as fileC:
|
||||
changelog = fileC.read()
|
||||
platformtools.dialog_ok('Kodi on Demand', 'Aggiornamenti applicati:\n' + changelog)
|
||||
if changelog.strip():
|
||||
platformtools.dialog_ok('Kodi on Demand', 'Aggiornamenti applicati:\n' + changelog)
|
||||
os.remove(xbmc.translatePath(changelogFile))
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -4,332 +4,52 @@ import xbmcgui
|
||||
|
||||
from core.tmdb import Tmdb
|
||||
from platformcode import config, logger
|
||||
from core import filetools
|
||||
|
||||
ID_BUTTON_CLOSE = 10003
|
||||
ID_BUTTON_PREVIOUS = 10025
|
||||
ID_BUTTON_NEXT = 10026
|
||||
ID_BUTTON_CANCEL = 10027
|
||||
ID_BUTTON_OK = 10028
|
||||
BACKGROUND = 30000
|
||||
LOADING = 30001
|
||||
SELECT = 30002
|
||||
|
||||
def imagepath(image):
|
||||
if len(image.split('.')) == 1: image += '.png'
|
||||
path = filetools.join(config.get_runtime_path(), 'resources', 'skins' , 'Default', 'media', 'Infoplus', image)
|
||||
return path
|
||||
|
||||
class InfoWindow(xbmcgui.WindowXMLDialog):
|
||||
otmdb = None
|
||||
|
||||
item_title = ""
|
||||
item_serie = ""
|
||||
item_temporada = 0
|
||||
item_episodio = 0
|
||||
result = {}
|
||||
|
||||
# PARA TMDB
|
||||
@staticmethod
|
||||
def get_language(lng):
|
||||
# Cambiamos el formato del Idioma
|
||||
languages = {
|
||||
'aa': 'Afar', 'ab': 'Abkhazian', 'af': 'Afrikaans', 'ak': 'Akan', 'sq': 'Albanian', 'am': 'Amharic',
|
||||
'ar': 'Arabic', 'an': 'Aragonese', 'as': 'Assamese', 'av': 'Avaric', 'ae': 'Avestan', 'ay': 'Aymara',
|
||||
'az': 'Azerbaijani', 'ba': 'Bashkir', 'bm': 'Bambara', 'eu': 'Basque', 'be': 'Belarusian', 'bn': 'Bengali',
|
||||
'bh': 'Bihari languages', 'bi': 'Bislama', 'bo': 'Tibetan', 'bs': 'Bosnian', 'br': 'Breton',
|
||||
'bg': 'Bulgarian', 'my': 'Burmese', 'ca': 'Catalan; Valencian', 'cs': 'Czech', 'ch': 'Chamorro',
|
||||
'ce': 'Chechen', 'zh': 'Chinese',
|
||||
'cu': 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic', 'cv': 'Chuvash',
|
||||
'kw': 'Cornish', 'co': 'Corsican', 'cr': 'Cree', 'cy': 'Welsh', 'da': 'Danish', 'de': 'German',
|
||||
'dv': 'Divehi; Dhivehi; Maldivian', 'nl': 'Dutch; Flemish', 'dz': 'Dzongkha', 'en': 'English',
|
||||
'eo': 'Esperanto', 'et': 'Estonian', 'ee': 'Ewe', 'fo': 'Faroese', 'fa': 'Persian', 'fj': 'Fijian',
|
||||
'fi': 'Finnish', 'fr': 'French', 'fy': 'Western Frisian', 'ff': 'Fulah', 'Ga': 'Georgian',
|
||||
'gd': 'Gaelic; Scottish Gaelic', 'ga': 'Irish', 'gl': 'Galician', 'gv': 'Manx',
|
||||
'el': 'Greek, Modern (1453-)', 'gn': 'Guarani', 'gu': 'Gujarati', 'ht': 'Haitian; Haitian Creole',
|
||||
'ha': 'Hausa', 'he': 'Hebrew', 'hz': 'Herero', 'hi': 'Hindi', 'ho': 'Hiri Motu', 'hr': 'Croatian',
|
||||
'hu': 'Hungarian', 'hy': 'Armenian', 'ig': 'Igbo', 'is': 'Icelandic', 'io': 'Ido',
|
||||
'ii': 'Sichuan Yi; Nuosu', 'iu': 'Inuktitut', 'ie': 'Interlingue; Occidental',
|
||||
'ia': 'Interlingua (International Auxiliary Language Association)', 'id': 'Indonesian', 'ik': 'Inupiaq',
|
||||
'it': 'Italian', 'jv': 'Javanese', 'ja': 'Japanese', 'kl': 'Kalaallisut; Greenlandic', 'kn': 'Kannada',
|
||||
'ks': 'Kashmiri', 'ka': 'Georgian', 'kr': 'Kanuri', 'kk': 'Kazakh', 'km': 'Central Khmer',
|
||||
'ki': 'Kikuyu; Gikuyu', 'rw': 'Kinyarwanda', 'ky': 'Kirghiz; Kyrgyz', 'kv': 'Komi', 'kg': 'Kongo',
|
||||
'ko': 'Korean', 'kj': 'Kuanyama; Kwanyama', 'ku': 'Kurdish', 'lo': 'Lao', 'la': 'Latin', 'lv': 'Latvian',
|
||||
'li': 'Limburgan; Limburger; Limburgish', 'ln': 'Lingala', 'lt': 'Lithuanian',
|
||||
'lb': 'Luxembourgish; Letzeburgesch', 'lu': 'Luba-Katanga', 'lg': 'Ganda', 'mk': 'Macedonian',
|
||||
'mh': 'Marshallese', 'ml': 'Malayalam', 'mi': 'Maori', 'mr': 'Marathi', 'ms': 'Malay', 'Mi': 'Micmac',
|
||||
'mg': 'Malagasy', 'mt': 'Maltese', 'mn': 'Mongolian', 'na': 'Nauru', 'nv': 'Navajo; Navaho',
|
||||
'nr': 'Ndebele, South; South Ndebele', 'nd': 'Ndebele, North; North Ndebele', 'ng': 'Ndonga',
|
||||
'ne': 'Nepali', 'nn': 'Norwegian Nynorsk; Nynorsk, Norwegian', 'nb': 'Bokmål, Norwegian; Norwegian Bokmål',
|
||||
'no': 'Norwegian', 'oc': 'Occitan (post 1500)', 'oj': 'Ojibwa', 'or': 'Oriya', 'om': 'Oromo',
|
||||
'os': 'Ossetian; Ossetic', 'pa': 'Panjabi; Punjabi', 'pi': 'Pali', 'pl': 'Polish', 'pt': 'Portuguese',
|
||||
'ps': 'Pushto; Pashto', 'qu': 'Quechua', 'ro': 'Romanian; Moldavian; Moldovan', 'rn': 'Rundi',
|
||||
'ru': 'Russian', 'sg': 'Sango', 'rm': 'Romansh', 'sa': 'Sanskrit', 'si': 'Sinhala; Sinhalese',
|
||||
'sk': 'Slovak', 'sl': 'Slovenian', 'se': 'Northern Sami', 'sm': 'Samoan', 'sn': 'Shona', 'sd': 'Sindhi',
|
||||
'so': 'Somali', 'st': 'Sotho, Southern', 'es': 'Spanish', 'sc': 'Sardinian', 'sr': 'Serbian', 'ss': 'Swati',
|
||||
'su': 'Sundanese', 'sw': 'Swahili', 'sv': 'Swedish', 'ty': 'Tahitian', 'ta': 'Tamil', 'tt': 'Tatar',
|
||||
'te': 'Telugu', 'tg': 'Tajik', 'tl': 'Tagalog', 'th': 'Thai', 'ti': 'Tigrinya',
|
||||
'to': 'Tonga (Tonga Islands)', 'tn': 'Tswana', 'ts': 'Tsonga', 'tk': 'Turkmen', 'tr': 'Turkish',
|
||||
'tw': 'Twi', 'ug': 'Uighur; Uyghur', 'uk': 'Ukrainian', 'ur': 'Urdu', 'uz': 'Uzbek', 've': 'Venda',
|
||||
'vi': 'Vietnamese', 'vo': 'Volapük', 'wa': 'Walloon', 'wo': 'Wolof', 'xh': 'Xhosa', 'yi': 'Yiddish',
|
||||
'yo': 'Yoruba', 'za': 'Zhuang; Chuang', 'zu': 'Zulu'}
|
||||
|
||||
return languages.get(lng, lng)
|
||||
|
||||
def get_scraper_data(self, data_in):
|
||||
self.otmdb = None
|
||||
# logger.debug(str(data_in))
|
||||
|
||||
if self.listData:
|
||||
# Data common to all listings
|
||||
infoLabels = self.scraper().get_infoLabels(origen=data_in)
|
||||
|
||||
if "original_language" in infoLabels:
|
||||
infoLabels["language"] = self.get_language(infoLabels["original_language"])
|
||||
infoLabels["puntuacion"] = "%s/10 (%s)" % (infoLabels.get("rating", "?"), infoLabels.get("votes", "N/A"))
|
||||
|
||||
self.result = infoLabels
|
||||
|
||||
def start(self, data, caption="Información del vídeo", item=None, scraper=Tmdb):
|
||||
"""
|
||||
It shows a window with the info of the video. Optionally, the title of the window can be indicated by means of the argument 'caption'.
|
||||
|
||||
If an item is passed as the 'data' argument use the Tmdb scrapper to find the video info
|
||||
In case of movies:
|
||||
Take the title from the following fields (in this order)
|
||||
1. contentTitle (this has priority 1)
|
||||
2. title (this has priority 2)
|
||||
The first one containing "something" interprets it as the title (it is important to make sure that the title is in
|
||||
your site)
|
||||
|
||||
In case of series:
|
||||
1. Find the season and episode in the contentSeason and contentEpisodeNumber fields
|
||||
2. Try to remove it from the video title (format: 1x01)
|
||||
|
||||
Here are two possible options:
|
||||
1. We have Season and episode
|
||||
Shows the information of the specific chapter
|
||||
2. We DO NOT have Season and episode
|
||||
In this case it shows the generic information of the series
|
||||
|
||||
If an InfoLabels object (see item.py) is passed as an argument 'data' it shows in the window directly
|
||||
the past information (without using the scrapper)
|
||||
Format:
|
||||
In case of movies:
|
||||
infoLabels ({
|
||||
"type" : "movie",
|
||||
"title": "Title of the movie",
|
||||
"original_title": "Original movie title",
|
||||
"date": "Release date",
|
||||
"language": "Original language of the movie",
|
||||
"rating": "Rating of the movie",
|
||||
"votes": "Number of votes",
|
||||
"genres": "Genres of the movie",
|
||||
"thumbnail": "Path for the thumbnail",
|
||||
"fanart": "Route for the fanart",
|
||||
"plot": "Synopsis of the movie"
|
||||
}
|
||||
In case of series:
|
||||
infoLabels ({
|
||||
"type" : "tv",
|
||||
"title": "Title of the series",
|
||||
"episode_title": "Episode title",
|
||||
"date": "Date of issue",
|
||||
"language": "Original language of the series",
|
||||
"rating": "Punctuation of the series",
|
||||
"votes": "Number of votes",
|
||||
"genres": "Genres of the series",
|
||||
"thumbnail": "Path for the thumbnail",
|
||||
"fanart": "Route for the fanart",
|
||||
"plot": "Synopsis of the episode or series",
|
||||
"seasons": "Number of Seasons",
|
||||
"season": "Season",
|
||||
"episodes": "Number of episodes of the season",
|
||||
"episode": "Episode"
|
||||
}
|
||||
If a list of InfoLabels () with the previous structure is passed as the 'data' argument, it shows the buttons
|
||||
'Previous' and 'Next' to scroll through the list. It also shows the 'Accept' and 'Cancel' buttons that
|
||||
call the function 'callback' of the channel from where the call is made, passing the element as parameters
|
||||
current (InfoLabels ()) or None respectively.
|
||||
|
||||
@param data: information to get scraper data.
|
||||
@type data: item, InfoLabels, list(InfoLabels)
|
||||
@param caption: window title.
|
||||
@type caption: str
|
||||
@param item: item for which the information window is to be displayed
|
||||
@type item: Item
|
||||
@param scraper: scraper that has the data of the movies or series to show in the window.
|
||||
@type scraper: Scraper
|
||||
"""
|
||||
|
||||
# We capture the parameters
|
||||
self.caption = caption
|
||||
def start(self, results, caption="", item=None, scraper=Tmdb):
|
||||
self.items = []
|
||||
self.response = None
|
||||
self.results = results
|
||||
self.item = item
|
||||
self.indexList = -1
|
||||
self.listData = None
|
||||
self.return_value = None
|
||||
self.scraper = scraper
|
||||
|
||||
logger.debug(data)
|
||||
if type(data) == list:
|
||||
self.listData = data
|
||||
self.indexList = 0
|
||||
data = self.listData[self.indexList]
|
||||
|
||||
self.get_scraper_data(data)
|
||||
|
||||
# Show window
|
||||
self.doModal()
|
||||
return self.return_value
|
||||
|
||||
def __init__(self, *args):
|
||||
self.caption = ""
|
||||
self.item = None
|
||||
self.listData = None
|
||||
self.indexList = 0
|
||||
self.return_value = None
|
||||
self.scraper = Tmdb
|
||||
logger.info('RESPONSE',self.response)
|
||||
return self.response
|
||||
|
||||
def onInit(self):
|
||||
#### Kodi 18 compatibility ####
|
||||
if config.get_platform(True)['num_version'] < 18:
|
||||
if xbmcgui.__version__ == "1.2":
|
||||
self.setCoordinateResolution(1)
|
||||
else:
|
||||
self.setCoordinateResolution(5)
|
||||
self.setCoordinateResolution(2)
|
||||
|
||||
# We put the title and the images
|
||||
self.getControl(10002).setLabel(self.caption)
|
||||
self.getControl(10004).setImage(self.result.get("fanart", ""))
|
||||
self.getControl(10005).setImage(self.result.get("thumbnail", "images/img_no_disponible.png"))
|
||||
for result in self.results:
|
||||
infoLabels = self.scraper().get_infoLabels(origen=result)
|
||||
it = xbmcgui.ListItem(infoLabels['title'])
|
||||
it.setProperty('fanart', infoLabels.get('fanart', ''))
|
||||
it.setProperty('thumbnail', infoLabels.get('thumbnail', imagepath('movie' if infoLabels['mediatype'] == 'movie' else 'tv')))
|
||||
it.setProperty('genre', infoLabels.get('genre', 'N/A'))
|
||||
it.setProperty('rating', str(infoLabels.get('rating', 'N/A')))
|
||||
it.setProperty('plot', str(infoLabels.get('plot', '')))
|
||||
it.setProperty('year', str(infoLabels.get('year', '')))
|
||||
self.items.append(it)
|
||||
|
||||
# We load the data for the movie format
|
||||
if self.result.get("mediatype", "movie") == "movie":
|
||||
self.getControl(10006).setLabel(config.get_localized_string(60377))
|
||||
self.getControl(10007).setLabel(self.result.get("title", "N/A"))
|
||||
self.getControl(10008).setLabel(config.get_localized_string(60378))
|
||||
self.getControl(10009).setLabel(self.result.get("originaltitle", "N/A"))
|
||||
self.getControl(100010).setLabel(config.get_localized_string(60379))
|
||||
self.getControl(100011).setLabel(self.result.get("language", "N/A"))
|
||||
self.getControl(100012).setLabel(config.get_localized_string(60380))
|
||||
self.getControl(100013).setLabel(self.result.get("puntuacion", "N/A"))
|
||||
self.getControl(100014).setLabel(config.get_localized_string(60381))
|
||||
self.getControl(100015).setLabel(self.result.get("release_date", "N/A"))
|
||||
self.getControl(100016).setLabel(config.get_localized_string(60382))
|
||||
self.getControl(100017).setLabel(self.result.get("genre", "N/A"))
|
||||
self.getControl(SELECT).addItems(self.items)
|
||||
self.getControl(BACKGROUND).setImage(self.items[0].getProperty('fanart'))
|
||||
self.getControl(LOADING).setVisible(False)
|
||||
self.setFocusId(SELECT)
|
||||
|
||||
# We load the data for the serial format
|
||||
else:
|
||||
self.getControl(10006).setLabel(config.get_localized_string(60383))
|
||||
self.getControl(10007).setLabel(self.result.get("title", "N/A"))
|
||||
self.getControl(10008).setLabel(config.get_localized_string(60379))
|
||||
self.getControl(10009).setLabel(self.result.get("language", "N/A"))
|
||||
self.getControl(100010).setLabel(config.get_localized_string(60380))
|
||||
self.getControl(100011).setLabel(self.result.get("puntuacion", "N/A"))
|
||||
self.getControl(100012).setLabel(config.get_localized_string(60382))
|
||||
self.getControl(100013).setLabel(self.result.get("genre", "N/A"))
|
||||
def onClick(self, control_id):
|
||||
if control_id == SELECT:
|
||||
self.response = self.results[self.getControl(SELECT).getSelectedPosition()]
|
||||
self.close()
|
||||
|
||||
if self.result.get("season"):
|
||||
self.getControl(100014).setLabel(config.get_localized_string(60384))
|
||||
self.getControl(100015).setLabel(self.result.get("temporada_nombre", "N/A"))
|
||||
self.getControl(100016).setLabel(config.get_localized_string(60385))
|
||||
self.getControl(100017).setLabel(self.result.get("season", "N/A") + " de " + self.result.get("seasons", "N/A"))
|
||||
if self.result.get("episode"):
|
||||
self.getControl(100014).setLabel(config.get_localized_string(60377))
|
||||
self.getControl(100015).setLabel(self.result.get("episode_title", "N/A"))
|
||||
self.getControl(100018).setLabel(config.get_localized_string(60386))
|
||||
self.getControl(100019).setLabel(self.result.get("episode", "N/A") + " de " + self.result.get("episodes", "N/A"))
|
||||
self.getControl(100020).setLabel(config.get_localized_string(60387))
|
||||
self.getControl(100021).setLabel(self.result.get("date", "N/A"))
|
||||
|
||||
# Synopsis
|
||||
if self.result['plot']:
|
||||
self.getControl(100022).setLabel(config.get_localized_string(60388))
|
||||
self.getControl(100023).setText(self.result.get("plot", "N/A"))
|
||||
else:
|
||||
self.getControl(100022).setLabel("")
|
||||
self.getControl(100023).setText("")
|
||||
|
||||
# We load the buttons if necessary
|
||||
self.getControl(10024).setVisible(self.indexList > -1) # Button group
|
||||
self.getControl(ID_BUTTON_PREVIOUS).setEnabled(self.indexList > 0) # Previous
|
||||
|
||||
if self.listData:
|
||||
m = len(self.listData)
|
||||
else:
|
||||
m = 1
|
||||
|
||||
self.getControl(ID_BUTTON_NEXT).setEnabled(self.indexList + 1 != m) # Following
|
||||
self.getControl(100029).setLabel("(%s/%s)" % (self.indexList + 1, m)) # x/m
|
||||
|
||||
# We put the focus in the Group of buttons, if "Previous" was deactivated the focus would go to the "Next" button
|
||||
# if "Next" tb is deactivated it will pass the focus to the "Cancel" button
|
||||
self.setFocus(self.getControl(10024))
|
||||
|
||||
return self.return_value
|
||||
|
||||
def onClick(self, _id):
|
||||
logger.info("onClick id=" + repr(_id))
|
||||
if _id == ID_BUTTON_PREVIOUS and self.indexList > 0:
|
||||
self.indexList -= 1
|
||||
self.get_scraper_data(self.listData[self.indexList])
|
||||
self.onInit()
|
||||
|
||||
elif _id == ID_BUTTON_NEXT and self.indexList < len(self.listData) - 1:
|
||||
self.indexList += 1
|
||||
self.get_scraper_data(self.listData[self.indexList])
|
||||
self.onInit()
|
||||
|
||||
elif _id == ID_BUTTON_OK or _id == ID_BUTTON_CLOSE or _id == ID_BUTTON_CANCEL:
|
||||
self.close()
|
||||
|
||||
if _id == ID_BUTTON_OK:
|
||||
self.return_value = self.listData[self.indexList]
|
||||
else:
|
||||
self.return_value = None
|
||||
|
||||
def onAction(self, action):
|
||||
logger.info("action=" + repr(action.getId()))
|
||||
action = action.getId()
|
||||
|
||||
# Find Focus
|
||||
focus = self.getFocusId()
|
||||
|
||||
# Left
|
||||
if action == 1:
|
||||
|
||||
if focus == ID_BUTTON_OK:
|
||||
self.setFocus(self.getControl(ID_BUTTON_CANCEL))
|
||||
|
||||
elif focus == ID_BUTTON_CANCEL:
|
||||
if self.indexList + 1 != len(self.listData):
|
||||
# Next
|
||||
self.setFocus(self.getControl(ID_BUTTON_NEXT))
|
||||
elif self.indexList > 0:
|
||||
# Previous
|
||||
self.setFocus(self.getControl(ID_BUTTON_PREVIOUS))
|
||||
|
||||
elif focus == ID_BUTTON_NEXT:
|
||||
if self.indexList > 0:
|
||||
# Next
|
||||
self.setFocus(self.getControl(ID_BUTTON_PREVIOUS))
|
||||
|
||||
# Right
|
||||
elif action == 2:
|
||||
|
||||
if focus == ID_BUTTON_PREVIOUS:
|
||||
if self.indexList + 1 != len(self.listData):
|
||||
# Next
|
||||
self.setFocus(self.getControl(ID_BUTTON_NEXT))
|
||||
else:
|
||||
# Cancel
|
||||
self.setFocus(self.getControl(ID_BUTTON_CANCEL))
|
||||
|
||||
elif focus == ID_BUTTON_NEXT:
|
||||
self.setFocus(self.getControl(ID_BUTTON_CANCEL))
|
||||
|
||||
elif focus == ID_BUTTON_CANCEL:
|
||||
self.setFocus(self.getControl(ID_BUTTON_OK))
|
||||
|
||||
# Up
|
||||
elif action == 3:
|
||||
self.setFocus(self.getControl(ID_BUTTON_CLOSE))
|
||||
|
||||
# Down
|
||||
elif action == 4:
|
||||
self.setFocus(self.getControl(ID_BUTTON_OK))
|
||||
# Press ESC or Back, simulate click on cancel button
|
||||
if action in [10, 92]:
|
||||
self.onClick(ID_BUTTON_CANCEL)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- General -->
|
||||
<category label="70168">
|
||||
<setting label="70786" type="lsep"/>
|
||||
<setting id="autostart" type="action" label="70706" action="RunPlugin(plugin://plugin.video.kod/?ew0KICAgICJhY3Rpb24iOiAiYXV0b3N0YXJ0IiwNCiAgICAiY2hhbm5lbCI6ICJzZXR0aW5nIg0KfQ==)" default="Off"/>
|
||||
<setting id="autostart" type="bool" label="70706" default="false"/>
|
||||
<setting label="70579" type="lsep"/>
|
||||
<setting id="addon_update_enabled" type="bool" label="70581" default="true"/>
|
||||
<setting id="addon_update_message" type="bool" label="70582" visible="eq(-1,true)" default="true"/>
|
||||
|
||||
@@ -1,375 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<window>
|
||||
<allowoverlays>false</allowoverlays>
|
||||
<animation type="WindowOpen" reversible="false">
|
||||
<effect type="slide" start="0,200" end="0,0" center="640,225" delay="160" tween="cubic" time="200" />
|
||||
<effect type="fade" delay="160" end="100" time="240" />
|
||||
</animation>
|
||||
<animation type="WindowClose" reversible="false">
|
||||
<effect type="slide" start="0,0" end="0,200" center="640,225" easing="in" tween="cubic" time="200" />
|
||||
<effect type="fade" start="100" end="0" time="240" />
|
||||
</animation>
|
||||
<controls>
|
||||
<control type="group" id="10001">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<depth>0.52</depth>
|
||||
<coordinates>
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
</coordinates>
|
||||
<controls>
|
||||
<!-- CLOSE BUTTON / BACKGROUND -->
|
||||
<control type="button">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<width>100%</width>
|
||||
<height>100%</height>
|
||||
<texturefocus colordiffuse="FF232323">white.png</texturefocus>
|
||||
<texturenofocus colordiffuse="FF232323">white.png</texturenofocus>
|
||||
<animation effect="fade" time="200">WindowOpen</animation>
|
||||
<animation effect="fade" time="200">WindowClose</animation>
|
||||
<onclick>Action(close)</onclick>
|
||||
</control>
|
||||
<!-- GROUP CONTROLS -->
|
||||
<control type="group">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<animation type="WindowOpen" reversible="false">
|
||||
<effect type="slide" start="0,100" end="0,0" delay="160" time="160" />
|
||||
<effect type="fade" delay="160" end="100" time="100" />
|
||||
</animation>
|
||||
<animation type="WindowClose" reversible="false">
|
||||
<effect type="slide" start="0,0" end="0,100" delay="160" time="160" />
|
||||
<effect type="fade" delay="160" start="100" end="0" time="100" />
|
||||
</animation>
|
||||
|
||||
<!-- BACKGROUND -->
|
||||
<control type="image" id='30000'>
|
||||
<width>1280</width>
|
||||
<height>720</height>
|
||||
<texture colordiffuse="FF555555"></texture>
|
||||
</control>
|
||||
|
||||
<!-- LOADING -->
|
||||
<control type="image" id='30001'>
|
||||
<top>355</top>
|
||||
<left>490</left>
|
||||
<width>300</width>
|
||||
<height>10</height>
|
||||
<texture>white.png</texture>
|
||||
<animation effect="zoom" pulse ="true" center="auto" start="0,100" end="100,100" time="1000" condition="Control.IsVisible(30001)">Conditional</animation>
|
||||
</control>
|
||||
|
||||
<!-- SELECTION -->
|
||||
<control type="fixedlist" id="30002">
|
||||
<top>40</top>
|
||||
<width>100%</width>
|
||||
<height>100%</height>
|
||||
<control type="image">
|
||||
<width>100%</width>
|
||||
<height>100%</height>
|
||||
<texture colordiffuse="FF232323">white.png</texture>
|
||||
</control>
|
||||
<!-- FANART -->
|
||||
<control type="image" id="10004">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<width>100%</width>
|
||||
<height>100%</height>
|
||||
<texture></texture>
|
||||
<colordiffuse>33FFFFFF</colordiffuse>
|
||||
</control>
|
||||
<!-- Header -->
|
||||
<control type="label" id="10002">
|
||||
<top>20</top>
|
||||
<left>0</left>
|
||||
<height>34</height>
|
||||
<width>100%</width>
|
||||
<font>font30_title</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<align>center</align>
|
||||
<aligny>center</aligny>
|
||||
<label>$ADDON[plugin.video.kod 70000]</label>
|
||||
</control>
|
||||
<!-- Close -->
|
||||
<control type="button" id="10003">
|
||||
<right>30</right>
|
||||
<top>25</top>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
<texturefocus colordiffuse="FFFFFFFF">close.png</texturefocus>
|
||||
<texturenofocus colordiffuse="55FFFFFF">close.png</texturenofocus>
|
||||
</control>
|
||||
<!-- LOCANDINA -->
|
||||
<control type="image" id="10005">
|
||||
<right>30</right>
|
||||
<top>110</top>
|
||||
<width>349</width>
|
||||
<height>500</height>
|
||||
<texture></texture>
|
||||
<aspectratio>keep</aspectratio>
|
||||
<animation type="WindowOpen" reversible="false">
|
||||
<effect type="slide" start="200,0" end="0,0" delay="300" tween="cubic" time="200" />
|
||||
<effect type="fade" delay="300" end="100" time="240" />
|
||||
</animation>
|
||||
<animation type="WindowClose" reversible="false">
|
||||
<effect type="slide" start="0,0" end="200,0" easing="in" tween="cubic" time="200" />
|
||||
<effect type="fade" start="100" end="0" time="240" />
|
||||
</animation>
|
||||
</control>
|
||||
<!-- Serie -->
|
||||
<control type="label" id="10006">
|
||||
<top>100</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="10007">
|
||||
<top>100</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="10008"> <!-- Lingua Originale -->
|
||||
<top>130</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="10009">
|
||||
<top>130</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100010"> <!-- Punteggio -->
|
||||
<top>160</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100011">
|
||||
<top>160</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100012"> <!-- Generi -->
|
||||
<top>190</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100013">
|
||||
<top>190</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100014">
|
||||
<top>220</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100015">
|
||||
<top>220</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100016">
|
||||
<top>250</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100017">
|
||||
<top>250</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100018">
|
||||
<top>280</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100019">
|
||||
<top>280</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100020">
|
||||
<top>310</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>200</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100021">
|
||||
<top>310</top>
|
||||
<left>250</left>
|
||||
<height>30</height>
|
||||
<width>365</width>
|
||||
<font>font13</font>
|
||||
<scrollsuffix> | </scrollsuffix>
|
||||
<scroll>true</scroll>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="label" id="100022"> <!-- Trama -->
|
||||
<top>330</top>
|
||||
<left>60</left>
|
||||
<height>30</height>
|
||||
<width>505</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>left</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="textbox" id="100023">
|
||||
<top>330</top>
|
||||
<left>250</left>
|
||||
<height>250</height>
|
||||
<width>550</width>
|
||||
<font>font13</font>
|
||||
<textcolor>0xFFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<wrapmultiline>true</wrapmultiline>
|
||||
<autoscroll delay="2000" time="1500" repeat="2000">true</autoscroll>
|
||||
<align>justify</align>
|
||||
<aligny>top</aligny>
|
||||
<label></label>
|
||||
</control>
|
||||
|
||||
<control type="group" id="10024">
|
||||
<bottom>60</bottom>
|
||||
<left>40</left>
|
||||
<width>760</width>
|
||||
<height>30</height>
|
||||
|
||||
<control type="button" id="10025">
|
||||
<top>0</top>
|
||||
<height>640</height>
|
||||
<viewtype>wrap</viewtype>
|
||||
<orientation>horizontal</orientation>
|
||||
<scrolltime tween="cubic" easing="out">300</scrolltime>
|
||||
<itemlayout height="640" width="180">
|
||||
<!-- Poster -->
|
||||
<control type="image">
|
||||
<bottom>0</bottom>
|
||||
<left>0</left>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
<textwidth>110</textwidth>
|
||||
<texturefocus colordiffuse="FF0081C2">white.png</texturefocus>
|
||||
<texturenofocus colordiffuse="000081C2">white.png</texturenofocus>
|
||||
<align>center</align>
|
||||
<aligny>center</aligny>
|
||||
<label>$ADDON[plugin.video.kod 70005]</label>
|
||||
<width>180</width>
|
||||
<height>270</height>
|
||||
<texture>$INFO[ListItem.Property(thumbnail)]</texture>
|
||||
<aspectratio>scale</aspectratio>
|
||||
<bordersize>10</bordersize>
|
||||
</control>
|
||||
<control type="button" id="10026">
|
||||
<top>0</top>
|
||||
<left>210</left>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
<textwidth>110</textwidth>
|
||||
<texturefocus colordiffuse="FF0081C2">white.png</texturefocus>
|
||||
<texturenofocus colordiffuse="000081C2">white.png</texturenofocus>
|
||||
<align>center</align>
|
||||
<aligny>center</aligny>
|
||||
<label>$ADDON[plugin.video.kod 70006]</label>
|
||||
</control>
|
||||
<control type="button" id="10027">
|
||||
<top>0</top>
|
||||
<left>420</left>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
<textwidth>110</textwidth>
|
||||
<texturefocus colordiffuse="FF0081C2">white.png</texturefocus>
|
||||
<texturenofocus colordiffuse="000081C2">white.png</texturenofocus>
|
||||
<align>center</align>
|
||||
<aligny>center</aligny>
|
||||
<label>$ADDON[plugin.video.kod 70002]</label>
|
||||
</control>
|
||||
<control type="button" id="10028">
|
||||
<top>0</top>
|
||||
<left>640</left>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
<textwidth>110</textwidth>
|
||||
<texturefocus colordiffuse="FF0081C2">white.png</texturefocus>
|
||||
<texturenofocus colordiffuse="000081C2">white.png</texturenofocus>
|
||||
<align>center</align>
|
||||
<aligny>center</aligny>
|
||||
<label>$ADDON[plugin.video.kod 70007]</label>
|
||||
</control>
|
||||
<control type="label" id="100029">
|
||||
</itemlayout>
|
||||
<focusedlayout height="640" width="480">
|
||||
<!-- Title -->
|
||||
<control type="textbox">
|
||||
<left>500</left>
|
||||
<top>10</top>
|
||||
<left>1080</left>
|
||||
<width>730</width>
|
||||
<height>30</height>
|
||||
<font>font30_title</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>00000000</shadowcolor>
|
||||
<label>[B]$INFO[ListItem.Label] [COLOR FFAAAAAA] $INFO[ListItem.Property(year)][/COLOR][/B] </label>
|
||||
<align>left</align>
|
||||
<aligny>center</aligny>
|
||||
</control>
|
||||
<!-- info -->
|
||||
<control type="textbox">
|
||||
<left>500</left>
|
||||
<top>50</top>
|
||||
<width>730</width>
|
||||
<height>30</height>
|
||||
<width>110</width>
|
||||
<font>font13</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>black</shadowcolor>
|
||||
<align>right</align>
|
||||
<aligny>center</aligny>
|
||||
<label></label>
|
||||
<shadowcolor>00000000</shadowcolor>
|
||||
<label>$ADDON[plugin.video.kod 60382] $INFO[ListItem.Property(genre)] | $ADDON[plugin.video.kod 60380] [B]$INFO[ListItem.Property(rating)][/B]</label>
|
||||
<align>left</align>
|
||||
</control>
|
||||
</control>
|
||||
<!-- Plot -->
|
||||
<control type="textbox">
|
||||
<left>500</left>
|
||||
<top>90</top>
|
||||
<width>730</width>
|
||||
<height>250</height>
|
||||
<font>font13</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>00000000</shadowcolor>
|
||||
<label>$INFO[ListItem.Property(plot)]</label>
|
||||
<autoscroll time="3000" delay="3000" repeat="3000">True</autoscroll>
|
||||
<align>left</align>
|
||||
</control>
|
||||
<!-- Poster -->
|
||||
<control type="image">
|
||||
<bottom>0</bottom>
|
||||
<left>0</left>
|
||||
<width>480</width>
|
||||
<height>640</height>
|
||||
<texture>$INFO[ListItem.Property(thumbnail)]</texture>
|
||||
<aspectratio>scale</aspectratio>
|
||||
<bordersize>10</bordersize>
|
||||
</control>
|
||||
</focusedlayout>
|
||||
</control>
|
||||
</controls>
|
||||
</control> <!-- GROUP CONTROLS END -->
|
||||
</controls>
|
||||
</window>
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
</control>
|
||||
<!-- LOADING -->
|
||||
<control type="image" id='30011'>
|
||||
<top>310</top>
|
||||
<left>590</left>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
<texture>Infoplus/loading.png</texture>
|
||||
<animation effect="rotate" center="640,360" start="0" end="-360" time="5000" loop="true" condition="Control.IsVisible(30011)">Conditional</animation>
|
||||
<top>355</top>
|
||||
<left>490</left>
|
||||
<width>300</width>
|
||||
<height>10</height>
|
||||
<texture>white.png</texture>
|
||||
<animation effect="zoom" pulse ="true" center="auto" start="0,100" end="100,100" time="1000" condition="Control.IsVisible(30011)">Conditional</animation>
|
||||
</control>
|
||||
<!-- TITLE -->
|
||||
<control type="textbox" id='30001'>
|
||||
@@ -90,7 +90,7 @@
|
||||
<font>font30_title</font>
|
||||
<textcolor>FFFFFFFF</textcolor>
|
||||
<shadowcolor>00000000</shadowcolor>
|
||||
<label>[B]$INFO[ListItem.Label] [COLOR FFAAAAAA]($INFO[ListItem.Property(year)])[/COLOR][/B] </label>
|
||||
<label>[B]$INFO[ListItem.Label] [COLOR FFAAAAAA]$INFO[ListItem.Property(year)][/COLOR][/B] </label>
|
||||
<align>left</align>
|
||||
<aligny>center</aligny>
|
||||
</control>
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
</control>
|
||||
<!-- LOADING -->
|
||||
<control type="image" id='30011'>
|
||||
<top>310</top>
|
||||
<left>590</left>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
<texture>Infoplus/loading.png</texture>
|
||||
<animation effect="rotate" center="640,360" start="0" end="-360" time="5000" loop="true" condition="Control.IsVisible(30011)">Conditional</animation>
|
||||
<top>355</top>
|
||||
<left>490</left>
|
||||
<width>300</width>
|
||||
<height>10</height>
|
||||
<texture>white.png</texture>
|
||||
<animation effect="zoom" pulse ="true" center="auto" start="0,100" end="100,100" time="1000" condition="Control.IsVisible(30011)">Conditional</animation>
|
||||
</control>
|
||||
<!-- TITLE -->
|
||||
<control type="textbox" id='30001'>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import urllib
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
|
||||
from core import httptools, support
|
||||
from core import scrapertools
|
||||
@@ -8,6 +11,7 @@ from platformcode import logger, config
|
||||
|
||||
headers = [['User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0']]
|
||||
|
||||
|
||||
def test_video_exists(page_url):
|
||||
logger.info("(page_url='%s')" % page_url)
|
||||
# page_url = re.sub('akvideo.stream/(?:video/|video\\.php\\?file_code=)?(?:embed-)?([a-zA-Z0-9]+)','akvideo.stream/video/\\1',page_url)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import urllib
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
|
||||
from core import httptools
|
||||
from core import scrapertools
|
||||
|
||||
@@ -8,7 +8,8 @@ from platformcode import config, logger
|
||||
def test_video_exists(page_url):
|
||||
logger.info("(page_url='%s')" % page_url)
|
||||
|
||||
data = httptools.downloadpage(page_url, cookies=False).data
|
||||
global data
|
||||
data = httptools.downloadpage(page_url).data
|
||||
if 'File you are looking for is not found.' in data:
|
||||
return False, config.get_localized_string(70449) % "Onlystream"
|
||||
|
||||
@@ -17,7 +18,7 @@ def test_video_exists(page_url):
|
||||
|
||||
def get_video_url(page_url, premium=False, user="", password="", video_password=""):
|
||||
logger.info("url=" + page_url)
|
||||
data = httptools.downloadpage(page_url).data
|
||||
global data
|
||||
# logger.info(data)
|
||||
video_urls = support.get_jwplayer_mediaurl(data, 'Onlystream')
|
||||
return video_urls
|
||||
|
||||
@@ -1,27 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# --------------------------------------------------------
|
||||
# Conector streamtape By Alfa development Group
|
||||
# --------------------------------------------------------
|
||||
import re
|
||||
from core import httptools
|
||||
from core import scrapertools
|
||||
from platformcode import logger, config
|
||||
from platformcode import logger
|
||||
import sys
|
||||
|
||||
PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
|
||||
|
||||
def test_video_exists(page_url):
|
||||
logger.info("(page_url='%s')" % page_url)
|
||||
global data
|
||||
data = httptools.downloadpage(page_url).data
|
||||
|
||||
referer = {"Referer": page_url}
|
||||
|
||||
data = httptools.downloadpage(page_url, headers=referer).data
|
||||
|
||||
if "Video not found" in data:
|
||||
return False, config.get_localized_string(70449) % "Streamtape"
|
||||
return False, "[streamtape] El archivo no existe o ha sido borrado"
|
||||
|
||||
return True, ""
|
||||
|
||||
|
||||
def get_video_url(page_url, premium=False, user="", password="", video_password=""):
|
||||
logger.info("url=" + page_url)
|
||||
|
||||
video_urls = []
|
||||
global data
|
||||
|
||||
url = scrapertools.find_single_match(data, 'id="videolink"[^>]+>\n?\s*//(.*?)<')
|
||||
if url:
|
||||
media_url = 'https://' + url + '&stream=1'
|
||||
video_urls.append([".mp4 [Streamtape]", media_url])
|
||||
|
||||
return video_urls
|
||||
url = "https:" + scrapertools.find_single_match(data, 'innerHTML = "([^"]+)')
|
||||
url = httptools.downloadpage(url, follow_redirects=False, only_headers=True).headers.get("location", "")
|
||||
video_urls.append(['MP4 [streamtape]', url])
|
||||
return video_urls
|
||||
@@ -1,7 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import time
|
||||
import urllib
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
|
||||
from core import httptools, support
|
||||
from core import scrapertools
|
||||
|
||||
@@ -9,7 +9,7 @@ def test_video_exists(page_url):
|
||||
page = httptools.downloadpage(page_url)
|
||||
global data
|
||||
data = page.data
|
||||
if page.code == 404:
|
||||
if page.code == 404 or 'File is no longer available' in data:
|
||||
return False, config.get_localized_string(70449)
|
||||
return True, ""
|
||||
|
||||
|
||||
12
service.py
12
service.py
@@ -8,6 +8,12 @@ import traceback
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
from platformcode import config
|
||||
# on kodi 18 its xbmc.translatePath, on 19 xbmcvfs.translatePath
|
||||
try:
|
||||
import xbmcvfs
|
||||
xbmc.translatePath = xbmcvfs.translatePath
|
||||
except:
|
||||
pass
|
||||
librerias = xbmc.translatePath(os.path.join(config.get_runtime_path(), 'lib'))
|
||||
sys.path.insert(0, librerias)
|
||||
|
||||
@@ -396,6 +402,12 @@ class AddonMonitor(xbmc.Monitor):
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info('Starting KoD service')
|
||||
if config.get_setting('autostart'):
|
||||
xbmc.executebuiltin('RunAddon(plugin.video.' + config.PLUGIN_NAME + ')')
|
||||
|
||||
# handling old autoexec method
|
||||
if config.is_autorun_enabled():
|
||||
config.enable_disable_autorun(True)
|
||||
monitor = AddonMonitor()
|
||||
|
||||
# mark as stopped all downloads (if we are here, probably kodi just started)
|
||||
|
||||
@@ -137,7 +137,11 @@ def search(item, text):
|
||||
json = load_json(item)
|
||||
if json:
|
||||
for key in json:
|
||||
peliculas(item, json, key, itemlist)
|
||||
if key not in ['sort']:
|
||||
if item.custom_search and key == 'menu':
|
||||
get_menu(item, json, key, itemlist)
|
||||
else:
|
||||
peliculas(item, json, key, itemlist)
|
||||
|
||||
return itemlist
|
||||
|
||||
|
||||
@@ -138,7 +138,10 @@ def renameFavourite(item):
|
||||
# Features to migrate old favorites (.txt)
|
||||
def readbookmark(filepath):
|
||||
logger.info()
|
||||
import urllib
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
|
||||
bookmarkfile = filetools.file_open(filepath)
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import re
|
||||
import urllib
|
||||
from channelselector import get_thumb
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
from core import httptools, scrapertools, support, tmdb, filetools
|
||||
from core.item import Item
|
||||
from platformcode import logger, config, platformtools
|
||||
|
||||
@@ -174,10 +174,10 @@ def channel_search(item):
|
||||
mode = item.mode
|
||||
|
||||
if item.infoLabels['tvshowtitle']:
|
||||
item.text = item.infoLabels['tvshowtitle'].split('-')[0]
|
||||
item.text = item.infoLabels['tvshowtitle'].split(' - ')[0]
|
||||
item.title = item.text
|
||||
elif item.infoLabels['title']:
|
||||
item.text = item.infoLabels['title'].split('-')[0]
|
||||
item.text = item.infoLabels['title'].split(' - ')[0]
|
||||
item.title = item.text
|
||||
|
||||
temp_search_file = config.get_temp_file('temp-search')
|
||||
@@ -235,6 +235,8 @@ def channel_search(item):
|
||||
if channel not in ch_list:
|
||||
ch_list[channel] = []
|
||||
ch_list[channel].extend(res.result()[1])
|
||||
if res.result()[2]:
|
||||
valid.extend(res.result()[2])
|
||||
|
||||
if progress.iscanceled():
|
||||
break
|
||||
@@ -261,21 +263,7 @@ def channel_search(item):
|
||||
ch_name = channel_titles[channel_list.index(key)]
|
||||
grouped = list()
|
||||
cnt += 1
|
||||
progress.update(old_div((cnt * 100), len(ch_list)), config.get_localized_string(60295) + '\n' + config.get_localized_string(60293))
|
||||
if item.mode != 'all':
|
||||
if len(value) == 1:
|
||||
if not value[0].action or config.get_localized_string(70006).lower() in value[0].title.lower():
|
||||
continue
|
||||
for elem in value:
|
||||
if not elem.infoLabels.get('year', ""):
|
||||
elem.infoLabels['year'] = '-'
|
||||
tmdb.set_infoLabels_itemlist(value, True, forced=True)
|
||||
for elem in value:
|
||||
if elem.infoLabels['tmdb_id'] == searched_id:
|
||||
elem.from_channel = key
|
||||
if not config.get_setting('unify'):
|
||||
elem.title += ' [%s]' % key
|
||||
valid.append(elem)
|
||||
progress.update(old_div((cnt * 100), len(ch_list)), config.get_localized_string(60295))
|
||||
|
||||
for it in value:
|
||||
if it.channel == item.channel:
|
||||
@@ -355,24 +343,38 @@ def channel_search(item):
|
||||
|
||||
def get_channel_results(item, module_dict, search_action):
|
||||
ch = search_action.channel
|
||||
max_results = 10
|
||||
results = list()
|
||||
valid = list()
|
||||
module = module_dict[ch]
|
||||
searched_id = item.infoLabels['tmdb_id']
|
||||
|
||||
try:
|
||||
results.extend(module.search(search_action, item.text))
|
||||
if len(results) == 1:
|
||||
if not results[0].action or config.get_localized_string(70006).lower() in results[0].title.lower():
|
||||
results.clear()
|
||||
elif item.mode != 'all':
|
||||
for elem in results:
|
||||
if not elem.infoLabels.get('year', ""):
|
||||
elem.infoLabels['year'] = '-'
|
||||
tmdb.set_infoLabels_item(elem)
|
||||
if elem.infoLabels['tmdb_id'] == searched_id:
|
||||
elem.from_channel = ch
|
||||
if not config.get_setting('unify'):
|
||||
elem.title += ' [%s]' % ch
|
||||
valid.append(elem)
|
||||
|
||||
if len(results) < 0 and len(results) < max_results and item.mode != 'all':
|
||||
# if len(results) < 0 and len(results) < max_results and item.mode != 'all':
|
||||
#
|
||||
# if len(results) == 1:
|
||||
# if not results[0].action or config.get_localized_string(30992).lower() in results[0].title.lower():
|
||||
# return [ch, []]
|
||||
#
|
||||
# results = get_info(results)
|
||||
|
||||
if len(results) == 1:
|
||||
if not results[0].action or config.get_localized_string(30992).lower() in results[0].title.lower():
|
||||
return [ch, []]
|
||||
|
||||
results = get_info(results)
|
||||
|
||||
return [search_action, results]
|
||||
return [search_action, results, valid]
|
||||
except:
|
||||
return [search_action, results]
|
||||
return [search_action, results, valid]
|
||||
|
||||
|
||||
def get_servers(item, module_dict):
|
||||
|
||||
@@ -15,50 +15,8 @@ from channelselector import get_thumb
|
||||
from core import filetools, servertools
|
||||
from core.item import Item
|
||||
from platformcode import config, logger, platformtools
|
||||
import xbmcgui
|
||||
|
||||
CHANNELNAME = "setting"
|
||||
AUTOSTART = config.is_autorun_enabled()
|
||||
|
||||
def mainlist(item):
|
||||
logger.info()
|
||||
|
||||
itemlist = list()
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60535), action="settings", folder=False,
|
||||
thumbnail=get_thumb("setting_0.png")))
|
||||
if AUTOSTART is False:
|
||||
autostart_mode = config.get_localized_string(70707)
|
||||
else:
|
||||
autostart_mode = config.get_localized_string(70708)
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=autostart_mode + " " + config.get_localized_string(70706), action="autostart", folder=False, thumbnail=get_thumb("setting_0.png")))
|
||||
|
||||
#itemlist.append(Item(channel=CHANNELNAME, title="", action="", folder=False, thumbnail=get_thumb("setting_0.png")))
|
||||
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60536) + ":", text_bold=True, action="", folder=False,
|
||||
thumbnail=get_thumb("setting_0.png")))
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=" " + config.get_localized_string(60537), action="menu_channels", folder=True,
|
||||
thumbnail=get_thumb("channels.png")))
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=" " + config.get_localized_string(60538), action="menu_servers", folder=True,
|
||||
thumbnail=get_thumb("channels.png")))
|
||||
itemlist.append(Item(channel="news", title=" " + config.get_localized_string(60539), action="menu_opciones",
|
||||
folder=True, thumbnail=get_thumb("news.png")))
|
||||
itemlist.append(Item(channel="search", title=" " + config.get_localized_string(60540), action="opciones", folder=True,
|
||||
thumbnail=get_thumb("search.png")))
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=" " + config.get_localized_string(60541), action="channel_config",
|
||||
config="downloads", folder=True, thumbnail=get_thumb("downloads.png")))
|
||||
|
||||
if config.get_videolibrary_support():
|
||||
itemlist.append(Item(channel="videolibrary", title=" " + config.get_localized_string(60542), action="channel_config",
|
||||
folder=True, thumbnail=get_thumb("videolibrary.png")))
|
||||
|
||||
if config.is_xbmc():
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=" " + config.get_localized_string(70253), action="setting_torrent",
|
||||
folder=True, thumbnail=get_thumb("channels_torrent.png")))
|
||||
#itemlist.append(Item(channel=CHANNELNAME, action="", title="", folder=False, thumbnail=get_thumb("setting_0.png")))
|
||||
itemlist.append(Item(channel=CHANNELNAME, title=config.get_localized_string(60544), action="submenu_tools", folder=True,
|
||||
thumbnail=get_thumb("setting_0.png")))
|
||||
|
||||
return itemlist
|
||||
|
||||
|
||||
def menu_channels(item):
|
||||
@@ -96,15 +54,6 @@ def channel_config(item):
|
||||
return platformtools.show_channel_settings(channelpath=filetools.join(config.get_runtime_path(), "channels", item.config))
|
||||
|
||||
|
||||
def autostart(item): # item required launcher.py line 265
|
||||
if config.enable_disable_autorun(AUTOSTART):
|
||||
logger.info('AUTOSTART ENABLED')
|
||||
# xbmcgui.Dialog().ok(config.get_localized_string(20000), config.get_localized_string(70709))
|
||||
else:
|
||||
logger.info('AUTOSTART ENABLED')
|
||||
# xbmcgui.Dialog().ok(config.get_localized_string(20000), config.get_localized_string(70710))
|
||||
|
||||
|
||||
# def setting_torrent(item):
|
||||
# logger.info()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from core.tmdb import Tmdb
|
||||
from core.scrapertools import htmlclean, decodeHtmlentities
|
||||
from core.support import thumb, typo, match, Item
|
||||
from platformcode import config, platformtools
|
||||
from platformcode.logger import info, error
|
||||
from platformcode import logger
|
||||
|
||||
info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json
|
||||
def_lang = info_language[config.get_setting("info_language", "videolibrary")]
|
||||
@@ -14,9 +14,9 @@ langs = ['auto', 'de', 'fr', 'pt', 'it', 'es-MX', 'ca', 'en', 'es']
|
||||
langt = langs[config.get_setting('tmdb', "tvmoviedb")]
|
||||
if langt == 'auto': langt = def_lang
|
||||
langt_alt = langs[config.get_setting('tmdb_alternativo', "tvmoviedb")]
|
||||
langs = ['auto', 'co', 'cl', 'ar', 'mx', 'en', 'es']
|
||||
langf = langs[config.get_setting('filmaff', "tvmoviedb")]
|
||||
if langf == 'auto': langf = 'en'
|
||||
# langs = ['auto', 'co', 'cl', 'ar', 'mx', 'en', 'es']
|
||||
# langf = langs[config.get_setting('filmaff', "tvmoviedb")]
|
||||
# if langf == 'auto': langf = 'en'
|
||||
langs = ['auto', 'de-de', 'fr-fr', 'pt-pt', 'it-it', 'es-MX', 'ca-es', 'en', 'es']
|
||||
langi = langs[config.get_setting('imdb', "tvmoviedb")]
|
||||
if langi == 'auto': langi = def_lang
|
||||
@@ -28,7 +28,7 @@ default_fan = filetools.join(config.get_runtime_path(), "fanart.jpg")
|
||||
|
||||
|
||||
def mainlist(item):
|
||||
info()
|
||||
logger.info()
|
||||
itemlist = [
|
||||
# TMDB
|
||||
# item.clone(title=typo(config.get_localized_string(70021), 'bold'), action=""),
|
||||
@@ -55,7 +55,7 @@ def configuracion(item):
|
||||
return ret
|
||||
|
||||
def search_star(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
itemlist = []
|
||||
item.type='movie'
|
||||
@@ -97,7 +97,7 @@ def search_(item):
|
||||
|
||||
|
||||
def searcing(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
new_item = Item(title=item.contentTitle, text=item.contentTitle.replace("+", " "), mode=item.contentType, infoLabels=item.infoLabels)
|
||||
|
||||
@@ -351,7 +351,7 @@ def list_tmdb(item):
|
||||
itemlist.append(new_item)
|
||||
except:
|
||||
import traceback
|
||||
error(traceback.format_exc())
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if orden:
|
||||
itemlist.sort(key=lambda item: item.infoLabels["year"], reverse=True)
|
||||
@@ -625,7 +625,7 @@ def indices_tmdb(item):
|
||||
|
||||
|
||||
def filter(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
from datetime import datetime
|
||||
list_controls = []
|
||||
@@ -705,7 +705,7 @@ def filtered(item, values):
|
||||
|
||||
|
||||
def musica_movie(item):
|
||||
info()
|
||||
logger.info()
|
||||
itemlist = []
|
||||
data = match(item).data
|
||||
matches = match(data, patron=r'<td class="left">([^<]+)<br><small>([^<]+)</small>.*?<td>(\d+:\d+).*?<p id="([^"]+)"').matches
|
||||
@@ -729,7 +729,7 @@ def list_imdb(item):
|
||||
url = 'http://www.imdb.com/search/title?' + item.url
|
||||
# data = httptools.downloadpage(url, headers=headers, replace_headers=True).data
|
||||
data = match(url, headers=headers).data
|
||||
info(data)
|
||||
logger.info(data)
|
||||
|
||||
# data = re.sub(r"\n|\r|\t| ", "", data)
|
||||
# data = re.sub(r"\s{2}", " ", data)
|
||||
@@ -812,7 +812,7 @@ def list_imdb(item):
|
||||
|
||||
|
||||
def filter_imdb(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
from datetime import datetime
|
||||
list_controls = []
|
||||
@@ -1392,7 +1392,7 @@ def indices_imdb(item):
|
||||
|
||||
|
||||
# def filter_fa(item):
|
||||
# info()
|
||||
# logger.info()
|
||||
|
||||
# from datetime import datetime
|
||||
# list_controls = []
|
||||
@@ -1494,7 +1494,7 @@ def indices_imdb(item):
|
||||
|
||||
|
||||
# def login_fa():
|
||||
# info()
|
||||
# logger.info()
|
||||
|
||||
# try:
|
||||
# user = config.get_setting("usuariofa", "tvmoviedb")
|
||||
@@ -1510,7 +1510,7 @@ def indices_imdb(item):
|
||||
# data = httptools.downloadpage("https://m.filmaffinity.com/%s/account.ajax.php?action=login" % langf, post=post).data
|
||||
|
||||
# if "Invalid username" in data:
|
||||
# error("Error en el login")
|
||||
# logger.error("Error en el login")
|
||||
# return False, config.get_localized_string(70330)
|
||||
# else:
|
||||
# post = "name=user-menu&url=http://m.filmaffinity.com/%s/main.php" % langf
|
||||
@@ -1519,11 +1519,11 @@ def indices_imdb(item):
|
||||
# userid = scrapertools.find_single_match(data, 'id-user=(\d+)')
|
||||
# if userid:
|
||||
# config.set_setting("userid", userid, "tvmoviedb")
|
||||
# info("Login correcto")
|
||||
# logger.info("Login correcto")
|
||||
# return True, ""
|
||||
# except:
|
||||
# import traceback
|
||||
# error(traceback.format_exc())
|
||||
# logger.error(traceback.format_exc())
|
||||
# return False, config.get_localized_string(70331)
|
||||
|
||||
|
||||
@@ -1644,7 +1644,7 @@ def indices_imdb(item):
|
||||
|
||||
# def votar_fa(item):
|
||||
# # Window to select the vote
|
||||
# info()
|
||||
# logger.info()
|
||||
|
||||
# list_controls = []
|
||||
# valores = {}
|
||||
@@ -1752,6 +1752,7 @@ def imagenes(item):
|
||||
# return itemlist
|
||||
elif "Imdb" in item.title:
|
||||
try:
|
||||
from core import httptools
|
||||
data = jsontools.load(httptools.downloadpage(item.images["imdb"]["url"], cookies=False).data)
|
||||
item.images["imdb"].pop("url")
|
||||
if data.get("allImages"):
|
||||
@@ -1920,7 +1921,7 @@ def acciones_trakt(item):
|
||||
ratings = []
|
||||
try:
|
||||
for i, entry in enumerate(data):
|
||||
info('ENTRY:',entry)
|
||||
logger.info('ENTRY:',entry)
|
||||
if i <= item.pagina: continue
|
||||
# try: entry = entry[item.args]
|
||||
# except: pass
|
||||
@@ -1974,7 +1975,7 @@ def acciones_trakt(item):
|
||||
if ratings[i]: new_item.title += typo("Trakt: %.2f | Tmdb: %.2f" % (ratings[i], new_item.infoLabels["rating"]), '_ [] color kod')
|
||||
except:
|
||||
import traceback
|
||||
error(traceback.format_exc())
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if "page" in item.url and len(itemlist) == 20:
|
||||
page = match(item.url, patron=r'page=(\d+)').match
|
||||
@@ -1996,7 +1997,7 @@ def acciones_trakt(item):
|
||||
|
||||
|
||||
def order_list(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
list_controls = []
|
||||
valores1 = ['rating', 'added', 'title', 'released', 'runtime', 'popularity', 'percentage', 'votes']
|
||||
@@ -2338,7 +2339,7 @@ def indices_mal(item):
|
||||
matches = match("https://myanimelist.net/anime.php", cookies=False, patronBlock=patronBlock, patron=patron).matches
|
||||
for url, title in matches:
|
||||
genero = title.split(" (", 1)[0]
|
||||
info(url_base, genero)
|
||||
logger.info(url_base, genero)
|
||||
thumbnail = url_base + genero.lower().replace(" ", "%20")
|
||||
if genero in ["Hentai", "Yaoi", "Yuri"] and not adult_mal:
|
||||
continue
|
||||
@@ -2387,7 +2388,7 @@ def season_mal(item):
|
||||
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))
|
||||
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="(.*?).jpg.*?<span class="preline">(.*?)</span>.*?<div class="info">\s*(.*?)\s*-.*?(\d{4}).*?title="Score">\s*(N/A|\d\.\d+)'
|
||||
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:
|
||||
if ("Hentai" in scrapedgenres or "Yaoi" in scrapedgenres or "Yuri" in scrapedgenres) and not adult_mal:
|
||||
@@ -2413,7 +2414,7 @@ def season_mal(item):
|
||||
else:
|
||||
args = "tv"
|
||||
contentType = "tvshow"
|
||||
thumbnail = thumbnail.replace("r/167x242/", "") + "l.jpg"
|
||||
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,
|
||||
contentTitle=scrapedtitle, contentType=contentType,
|
||||
@@ -2487,7 +2488,7 @@ def detail_staff(item):
|
||||
patron_bio = r'<?<div class="spaceit_pad">(.*?)</td>'
|
||||
bio = match(data, patron=patron_bio).match
|
||||
bio = htmlclean(bio.replace("</div>", "\n"))
|
||||
info(bio)
|
||||
logger.info(bio)
|
||||
infoLabels = {'plot': bio}
|
||||
if not "No voice acting roles" in data:
|
||||
itemlist.append(Item(channel=item.channel, title=typo(config.get_localized_string(70374),'bold bullet'), action="", thumbnail=item.thumbnail, infoLabels=infoLabels))
|
||||
@@ -2550,7 +2551,7 @@ def searching_mal(item):
|
||||
title += " (%s)" % year
|
||||
except:
|
||||
import traceback
|
||||
error(traceback.format_exc())
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if tipo == "Movie" or tipo == "OVA":
|
||||
infolabels["mediatype"] = "movie"
|
||||
@@ -2625,7 +2626,7 @@ def info_anidb(item, itemlist, url):
|
||||
|
||||
|
||||
def filter_mal(item):
|
||||
info()
|
||||
logger.info()
|
||||
|
||||
list_controls = []
|
||||
valores = {}
|
||||
@@ -2703,7 +2704,7 @@ def callback_mal(item, values):
|
||||
|
||||
def musica_anime(item):
|
||||
# List available anime and songs similar to the anime title
|
||||
info()
|
||||
logger.info()
|
||||
itemlist = []
|
||||
|
||||
data = match("http://www.freeanimemusic.org/song_search.php", post=item.post).data
|
||||
@@ -2738,7 +2739,7 @@ def musica_anime(item):
|
||||
|
||||
|
||||
def login_mal(from_list=False):
|
||||
info()
|
||||
logger.info()
|
||||
from core import httptools
|
||||
from base64 import b64decode as bdec
|
||||
|
||||
@@ -2762,16 +2763,16 @@ def login_mal(from_list=False):
|
||||
response = httptools.downloadpage("https://myanimelist.net/login.php?from=%2F", post=post)
|
||||
|
||||
if not re.search(r'(?i)' + user, response.data):
|
||||
error("Login failed")
|
||||
logger.error("Login failed")
|
||||
return False, config.get_localized_string(70330), user
|
||||
else:
|
||||
if generic:
|
||||
return False, config.get_localized_string(70393), user
|
||||
info("Correct login")
|
||||
logger.info("Correct login")
|
||||
return True, "", user
|
||||
except:
|
||||
import traceback
|
||||
error(traceback.format_exc())
|
||||
logger.error(traceback.format_exc())
|
||||
return False, config.get_localized_string(70331) , ''
|
||||
|
||||
|
||||
@@ -2799,7 +2800,7 @@ def cuenta_mal(item):
|
||||
|
||||
def items_mal(item):
|
||||
# Scraper for personal lists
|
||||
info()
|
||||
logger.info()
|
||||
itemlist = []
|
||||
data = match(item.url).data
|
||||
|
||||
|
||||
16
tests/run.sh
Executable file
16
tests/run.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
rm tests/home/userdata/addon_data/plugin.video.kod/settings_channels/*.json
|
||||
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/kod_db.sqlite
|
||||
python -m pip install --upgrade pip
|
||||
pip install sakee
|
||||
pip install html-testRunner
|
||||
pip install parameterized
|
||||
export PYTHONPATH=$PWD
|
||||
export KODI_INTERACTIVE=0
|
||||
export KODI_HOME=$PWD/tests/home
|
||||
if (( $# >= 1 ))
|
||||
then
|
||||
export KOD_TST_CH=$1
|
||||
fi
|
||||
python tests/test_generic.py
|
||||
@@ -120,7 +120,7 @@ chNumRis = {
|
||||
'Serie TV': 12
|
||||
},
|
||||
'serietvonline': {
|
||||
'Film': 50,
|
||||
'Film': 25,
|
||||
'Serie TV': 35
|
||||
},
|
||||
'tantifilm': {
|
||||
@@ -135,6 +135,8 @@ channels = []
|
||||
channel_list = channelselector.filterchannels("all") if 'KOD_TST_CH' not in os.environ else [Item(channel=os.environ['KOD_TST_CH'], action="mainlist")]
|
||||
logger.info(channel_list)
|
||||
ret = []
|
||||
|
||||
logger.record = True
|
||||
for chItem in channel_list:
|
||||
try:
|
||||
ch = chItem.channel
|
||||
@@ -143,6 +145,7 @@ for chItem in channel_list:
|
||||
hasChannelConfig = False
|
||||
mainlist = module.mainlist(Item())
|
||||
menuItemlist = {}
|
||||
logMenu = {}
|
||||
serversFound = {}
|
||||
|
||||
for it in mainlist:
|
||||
@@ -155,6 +158,8 @@ for chItem in channel_list:
|
||||
continue
|
||||
itemlist = getattr(module, it.action)(it)
|
||||
menuItemlist[it.title] = itemlist
|
||||
logMenu[it.title] = logger.recordedLog
|
||||
logger.recordedLog = ''
|
||||
|
||||
# some sites might have no link inside, but if all results are without servers, there's something wrong
|
||||
for resIt in itemlist:
|
||||
@@ -165,16 +170,22 @@ for chItem in channel_list:
|
||||
serversFound[it.title] = [resIt]
|
||||
|
||||
if serversFound[it.title]:
|
||||
if hasattr(module, 'play'):
|
||||
serversFound[it.title] = [getattr(module, 'play')(resIt)[0] for srv in serversFound[it.title]]
|
||||
servers.extend(
|
||||
{'name': srv.server.lower(), 'server': srv} for srv in serversFound[it.title] if srv.server)
|
||||
break
|
||||
|
||||
channels.append(
|
||||
{'ch': ch, 'hasChannelConfig': hasChannelConfig, 'mainlist': mainlist, 'menuItemlist': menuItemlist,
|
||||
'serversFound': serversFound, 'module': module})
|
||||
'serversFound': serversFound, 'module': module, 'logMenu': logMenu})
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
print(logger.recordedLog)
|
||||
logger.recordedLog = ''
|
||||
|
||||
logger.record = False
|
||||
|
||||
from specials import news
|
||||
dictNewsChannels, any_active = news.get_channels_list()
|
||||
@@ -203,12 +214,26 @@ class GenericChannelTest(unittest.TestCase):
|
||||
break
|
||||
|
||||
|
||||
def testnameCh(cls, num, params_dict):
|
||||
return 'channels.' + params_dict['ch'] + ' -> ' + params_dict['title']
|
||||
|
||||
|
||||
def testnameSrv(cls, num, params_dict):
|
||||
return 'servers.' + params_dict['name']
|
||||
|
||||
|
||||
@parameterized.parameterized_class(
|
||||
[{'ch': ch['ch'], 'title': title, 'itemlist': itemlist, 'serversFound': ch['serversFound'][title] if title in ch['serversFound'] else True, 'module': ch['module']} for ch in channels for
|
||||
title, itemlist in ch['menuItemlist'].items()])
|
||||
[{'ch': ch['ch'], 'title': title, 'itemlist': itemlist,
|
||||
'serversFound': ch['serversFound'][title] if title in ch['serversFound'] else True,
|
||||
'module': ch['module'], 'log': ch['logMenu'][title]}
|
||||
for ch in channels
|
||||
for title, itemlist in ch['menuItemlist'].items()], class_name_func=testnameCh)
|
||||
class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
def test_menu(self):
|
||||
print('testing ' + self.ch + ' --> ' + self.title)
|
||||
|
||||
logger.info(self.log)
|
||||
|
||||
self.assertTrue(self.module.host, 'channel ' + self.ch + ' has not a valid hostname')
|
||||
self.assertTrue(self.itemlist, 'channel ' + self.ch + ' -> ' + self.title + ' is empty')
|
||||
self.assertTrue(self.serversFound,
|
||||
@@ -217,7 +242,7 @@ class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
if self.ch in chNumRis: # i know how much results should be
|
||||
for content in chNumRis[self.ch]:
|
||||
if content in self.title:
|
||||
risNum = len([i for i in self.itemlist if not i.nextPage]) # not count nextpage
|
||||
risNum = len([i for i in self.itemlist if i.title != typo(config.get_localized_string(30992), 'color kod bold')]) # not count nextpage
|
||||
self.assertEqual(chNumRis[self.ch][content], risNum,
|
||||
'channel ' + self.ch + ' -> ' + self.title + ' returned wrong number of results<br>'
|
||||
+ str(risNum) + ' but should be ' + str(chNumRis[self.ch][content]) + '<br>' +
|
||||
@@ -246,48 +271,46 @@ class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
self.assertTrue(nextPageItemlist,
|
||||
'channel ' + self.ch + ' -> ' + self.title + ' has nextpage not working')
|
||||
|
||||
print('<br>test passed')
|
||||
print('test passed')
|
||||
|
||||
|
||||
@parameterized.parameterized_class(serversFinal)
|
||||
@parameterized.parameterized_class(serversFinal, class_name_func=testnameSrv)
|
||||
class GenericServerTest(unittest.TestCase):
|
||||
def test_get_video_url(self):
|
||||
module = __import__('servers.%s' % self.name, fromlist=["servers.%s" % self.name])
|
||||
page_url = self.server.url
|
||||
print('testing ' + page_url)
|
||||
self.assert_(hasattr(module, 'test_video_exists'), self.name + ' has no test_video_exists')
|
||||
try:
|
||||
if module.test_video_exists(page_url)[0]:
|
||||
urls = module.get_video_url(page_url)
|
||||
server_parameters = servertools.get_server_parameters(self.name)
|
||||
self.assertTrue(urls or server_parameters.get("premium"),
|
||||
self.name + ' scraper did not return direct urls for ' + page_url)
|
||||
print(urls)
|
||||
for u in urls:
|
||||
spl = u[1].split('|')
|
||||
if len(spl) == 2:
|
||||
directUrl, headersUrl = spl
|
||||
else:
|
||||
directUrl, headersUrl = spl[0], ''
|
||||
headers = {}
|
||||
if headersUrl:
|
||||
for name in headersUrl.split('&'):
|
||||
h, v = name.split('=')
|
||||
h = str(h)
|
||||
headers[h] = str(v)
|
||||
print(headers)
|
||||
if 'magnet:?' in directUrl: # check of magnet links not supported
|
||||
continue
|
||||
page = downloadpage(directUrl, headers=headers, only_headers=True, use_requests=True)
|
||||
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')
|
||||
contentType = page.headers['Content-Type']
|
||||
self.assert_(contentType.startswith(
|
||||
'video') or 'mpegurl' in contentType or 'octet-stream' in contentType or 'dash+xml' in contentType,
|
||||
self.name + ' scraper did not return valid url for link ' + page_url + '<br>Direct url: ' + directUrl + '<br>Content-Type: ' + contentType)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if module.test_video_exists(page_url)[0]:
|
||||
urls = module.get_video_url(page_url)
|
||||
server_parameters = servertools.get_server_parameters(self.name)
|
||||
self.assertTrue(urls or server_parameters.get("premium"),
|
||||
self.name + ' scraper did not return direct urls for ' + page_url)
|
||||
print(urls)
|
||||
for u in urls:
|
||||
spl = u[1].split('|')
|
||||
if len(spl) == 2:
|
||||
directUrl, headersUrl = spl
|
||||
else:
|
||||
directUrl, headersUrl = spl[0], ''
|
||||
headers = {}
|
||||
if headersUrl:
|
||||
for name in headersUrl.split('&'):
|
||||
h, v = name.split('=')
|
||||
h = str(h)
|
||||
headers[h] = str(v)
|
||||
print(headers)
|
||||
if 'magnet:?' in directUrl: # check of magnet links not supported
|
||||
continue
|
||||
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.assertLess(page.code, 400, self.name + ' scraper returned a ' + str(page.code) + ' link')
|
||||
contentType = page.headers['Content-Type']
|
||||
self.assert_(contentType.startswith(
|
||||
'video') or 'mpegurl' in contentType or 'octet-stream' in contentType or 'dash+xml' in contentType,
|
||||
self.name + ' scraper did not return valid url for link ' + page_url + '<br>Direct url: ' + directUrl + '<br>Content-Type: ' + contentType)
|
||||
print('test passed')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user