KoD 0.8.1

- riorganizzate le impostazioni
- aggiunte descrizioni tag qualità su cb01 (presto anche sugli altri)
- aggiunto il supporto alle serie di polpotv
- fixato server mystream
- fix Rinumerazione per episodi Nuovi
This commit is contained in:
marco
2020-03-14 17:03:57 +01:00
parent c642ddc358
commit 3cdedad7e8
413 changed files with 10944 additions and 1540 deletions

View File

@@ -10,6 +10,7 @@ from platformcode import config, logger
DEFAULT_UPDATE_URL = "/channels/"
dict_channels_parameters = dict()
default_file = dict()
remote_path = 'https://raw.githubusercontent.com/kodiondemand/media/master/'
@@ -177,7 +178,9 @@ def get_lang(channel_name):
def get_default_settings(channel_name):
from core import filetools
default_path = filetools.join(config.get_runtime_path(), 'default_channel_settings' + '.json')
default_file = jsontools.load(filetools.read(default_path))
global default_file
if not default_file:
default_file = jsontools.load(filetools.read(default_path))
channel_path = filetools.join(config.get_runtime_path(), 'channels', channel_name + '.json')
adult_path = filetools.join(config.get_runtime_path(), 'channels', 'porn', channel_name + '.json')
@@ -258,7 +261,7 @@ def get_channel_setting(name, channel, default=None):
Devuelve el valor del parametro 'name' en la configuracion propia del canal 'channel'.
Busca en la ruta \addon_data\plugin.video.alfa\settings_channels el archivo channel_data.json y lee
Busca en la ruta \addon_data\plugin.video.kod\settings_channels el archivo channel_data.json y lee
el valor del parametro 'name'. Si el archivo channel_data.json no existe busca en la carpeta channels el archivo
channel.json y crea un archivo channel_data.json antes de retornar el valor solicitado. Si el parametro 'name'
tampoco existe en el el archivo channel.json se devuelve el parametro default.
@@ -317,7 +320,7 @@ def set_channel_setting(name, value, channel):
Establece 'value' como el valor del parametro 'name' en la configuracion propia del canal 'channel'.
Devuelve el valor cambiado o None si la asignacion no se ha podido completar.
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.kod\settings_channels el
archivo channel_data.json y establece el parametro 'name' al valor indicado por 'value'.
Si el parametro 'name' no existe lo añade, con su valor, al archivo correspondiente.

View File

@@ -12,11 +12,10 @@ except ImportError:
import urllib, urlparse, cookielib
import inspect, os, time, json
import os, time, json
from threading import Lock
from core.jsontools import to_utf8
from platformcode import config, logger
from platformcode.logger import WebErrorException
from core import scrapertools
# Get the addon version
@@ -42,6 +41,13 @@ if HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT == 0: HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT =
# Random use of User-Agents, if nad is not specified
HTTPTOOLS_DEFAULT_RANDOM_HEADERS = False
domainCF = list()
channelsCF = ['guardaserieclick', 'casacinema', 'dreamsub', 'ilgeniodellostreaming', 'piratestreaming', 'altadefinizioneclick', 'altadefinizione01_link']
otherCF = ['altadefinizione-nuovo.link', 'wstream.video', 'akvideo.stream', 'backin.net']
for ch in channelsCF:
domainCF.append(urlparse.urlparse(config.get_channel_url(name=ch)).hostname)
domainCF.extend(otherCF)
def get_user_agent():
# Returns the global user agent to be used when necessary for the url.
return default_headers["User-Agent"]
@@ -253,10 +259,9 @@ def downloadpage(url, **opt):
url = scrapertools.unescape(url)
load_cookies()
domain = urlparse.urlparse(url).netloc
global domainCF
CF = False
if domain in ['www.guardaserie.media', 'casacinema.space', 'wstream.video', 'akvideo.stream', 'backin.net',
'dreamsub.stream', 'altadefinizione-nuovo.link', 'ilgeniodellostreaming.si', 'www.piratestreaming.gratis',
'altadefinizione.style']:
if domain in domainCF:
from lib import cloudscraper
session = cloudscraper.create_scraper()
CF = True

View File

@@ -353,7 +353,7 @@ class Item(object):
def fromurl(self, url):
"""
Genera un item a partir de una cadena de texto. La cadena puede ser creada por la funcion tourl() o tener
el formato antiguo: plugin://plugin.video.alfa/?channel=... (+ otros parametros)
el formato antiguo: plugin://plugin.video.kod/?channel=... (+ otros parametros)
Uso: item.fromurl("cadena")
@param url: url

View File

@@ -735,8 +735,12 @@ def check_list_links(itemlist, numero='', timeout=3):
El parámetro numero indica cuantos enlaces hay que verificar (0:5, 1:10, 2:15, 3:20)
El parámetro timeout indica un tope de espera para descargar la página
"""
numero = ((int(numero) + 1) * 5) if numero != '' else 10
from lib.concurrent import futures
numero = numero if numero > 4 else ((int(numero) + 1) * 5) if numero != '' else 5
import sys
if sys.version_info[0] >= 3:
from concurrent import futures
else:
from concurrent_py2 import futures
with futures.ThreadPoolExecutor() as executor:
checked = []
for it in itemlist:

View File

@@ -5,7 +5,13 @@ import base64
import inspect
import os
import re
from concurrent import futures
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
if PY3:
from concurrent import futures
else:
from concurrent_py2 import futures
try:
import urllib.request as urllib
@@ -20,7 +26,9 @@ from core import httptools, scrapertools, servertools, tmdb, channeltools
from core.item import Item
from lib import unshortenit
from platformcode import logger, config
from specials import autoplay
from specials import autoplay, shortcuts
CONTEXT =shortcuts.context()
def hdpass_get_servers(item):
def get_hosts(url, quality):
@@ -295,7 +303,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
contentLanguage = lang1,
contentEpisodeNumber=episode if episode else '',
news= item.news if item.news else '',
other = scraped['other'] if scraped['other'] else ''
other = scraped['other'] if scraped['other'] else '',
context = CONTEXT
)
# for lg in list(set(listGroups).difference(known_keys)):
@@ -420,7 +429,7 @@ def scrape(func):
# next page for pagination
if pagination and len(matches) > pag * pagination and not search:
if inspect.stack()[1][3] != 'get_newest':
if inspect.stack()[1][3] not in ['newest','get_newest']:
itemlist.append(
Item(channel=item.channel,
action = item.action,
@@ -616,7 +625,8 @@ def menuItem(itemlist, filename, title='', action='', url='', contentType='movie
url = url,
extra = extra,
args = args,
contentType = contentType
contentType = contentType,
context = CONTEXT
))
# Apply auto Thumbnails at the menus
@@ -664,7 +674,7 @@ def menu(func):
url = host + var[0] if len(var) > 0 else '',
action = var[1] if len(var) > 1 else 'peliculas',
args=var[2] if len(var) > 2 else '',
contentType= var[3] if len(var) > 3 else 'movie',)
contentType= var[3] if len(var) > 3 else 'movie')
# Make MAIN MENU
elif dictUrl[name] is not None:
@@ -683,7 +693,7 @@ def menu(func):
url = host + var[0] if len(var) > 0 else '',
action = var[1] if len(var) > 1 else 'peliculas',
args=var[2] if len(var) > 2 else '',
contentType= var[3] if len(var) > 3 else 'movie' if name == 'film' else 'tvshow',)
contentType= var[3] if len(var) > 3 else 'movie' if name == 'film' else 'tvshow')
# add search menu for category
if 'search' not in args: menuItem(itemlist, filename, config.get_localized_string(70741) % title + ' … submenu bold', 'search', host + url, contentType='movie' if name == 'film' else 'tvshow')
@@ -719,56 +729,45 @@ def typo(string, typography=''):
kod_color = '0xFF65B3DA' #'0xFF0081C2'
try: string = str(string)
except: string = str(string.encode('utf8'))
typography2 = match(string, patron=r'\{([^\}]+)\}').match
# Check if the typographic attributes are in the string or outside
if typography2:
string = re.sub(r'(\s*\{[^\}]+\})', '', string)
typography += ' ' + typography2
if typography:
string = string + ' ' + typography
if config.get_localized_string(30992) in string:
string = string + ' >'
# If there are no attributes, it applies the default ones
attribute = ['[]','()','{}','submenu','color','bold','italic','_','--','[B]','[I]','[COLOR]']
# movie_word_list = ['film', 'serie', 'tv', 'anime', 'cinema', 'sala']
# search_word_list = ['cerca']
# categories_word_list = ['genere', 'categoria', 'categorie', 'ordine', 'lettera', 'anno', 'alfabetico', 'a-z', 'menu']
# if not any(word in string for word in attribute):
# if any(word in string.lower() for word in search_word_list):
# string = '[COLOR '+ kod_color +']' + string + '[/COLOR]'
# elif any(word in string.lower() for word in categories_word_list):
# string = ' > ' + string
# elif any(word in string.lower() for word in movie_word_list):
# string = '[B]' + string + '[/B]'
attribute = ['[]','()','submenu','color','bold','italic','_','--','[B]','[I]','[COLOR]']
# Otherwise it uses the typographical attributes of the string
# else:
if '[]' in string:
string = '[' + re.sub(r'\s\[\]','',string) + ']'
string = '[' + re.sub(r'\s*\[\]','',string) + ']'
if '()' in string:
string = '(' + re.sub(r'\s\(\)','',string) + ')'
if '{}' in string:
string = '{' + re.sub(r'\s\{\}','',string) + '}'
string = '(' + re.sub(r'\s*\(\)','',string) + ')'
if 'submenu' in string:
string = "•• " + re.sub(r'\ssubmenu','',string)
string = "•• " + re.sub(r'\s*submenu','',string)
if 'color' in string:
color = scrapertools.find_single_match(string, 'color ([a-z]+)')
if color == 'kod' or '': color = kod_color
string = '[COLOR '+ color +']' + re.sub(r'\scolor\s([a-z]+)','',string) + '[/COLOR]'
if 'bold' in string:
string = '[B]' + re.sub(r'\sbold','',string) + '[/B]'
string = '[B]' + re.sub(r'\s*bold','',string) + '[/B]'
if 'italic' in string:
string = '[I]' + re.sub(r'\sitalic','',string) + '[/I]'
string = '[I]' + re.sub(r'\s*italic','',string) + '[/I]'
if '_' in string:
string = ' ' + re.sub(r'\s_','',string)
string = ' ' + re.sub(r'\s*_','',string)
if '--' in string:
string = ' - ' + re.sub(r'\s--','',string)
string = ' - ' + re.sub(r'\s*--','',string)
if 'bullet' in string:
string = '[B]' + "" + '[/B] ' + re.sub(r'\sbullet','',string)
string = '[B]' + "" + '[/B] ' + re.sub(r'\s*bullet','',string)
if 'capitalize' in string.lower():
string = re.sub(r'\s*capitalize','',string).capitalize()
if 'uppercase' in string.lower():
string = re.sub(r'\s*uppercase','',string).upper()
if 'lowercase' in string.lower():
string = re.sub(r'\s*lowercase','',string).lower()
if '{}' in string:
string = re.sub(r'\s*\{\}','',string)
return string
@@ -818,12 +817,15 @@ def match(item_url_string, **args):
# check type of item_url_string
if string:
data = item_url_string
elif type(item_url_string) == str:
if item_url_string.startswith('http'): url = item_url_string
else : data = item_url_string
else:
elif isinstance(item_url_string, Item):
# if item_url_string is an item use item.url as url
url = item_url_string.url
else:
if item_url_string.startswith('http'): url = item_url_string
else : data = item_url_string
# else:
# # if item_url_string is an item use item.url as url
# url = item_url_string.url
# if there is a url, download the page
if url:
@@ -1021,7 +1023,7 @@ def pagination(itemlist, item, page, perpage, function_level=1):
thumbnail=thumb()))
return itemlist
def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True, down_load=True):
def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True, down_load=True, patronTag=None):
if not data and not itemlist:
data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data
@@ -1057,6 +1059,8 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
videoitem.contentType = item.contentType
verifiedItemlist.append(videoitem)
if patronTag:
addQualityTag(item, verifiedItemlist, data, patronTag)
return controls(verifiedItemlist, item, AutoPlay, CheckLinks, down_load)
def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True):
@@ -1079,11 +1083,9 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True):
if CL and not AP:
if get_setting('checklinks', item.channel):
checklinks = get_setting('checklinks', item.channel)
else:
checklinks = get_setting('checklinks')
if get_setting('checklinks_number', item.channel):
checklinks_number = get_setting('checklinks_number', item.channel)
else:
checklinks = get_setting('checklinks')
checklinks_number = get_setting('checklinks_number')
itemlist = servertools.check_list_links(itemlist, checklinks_number)
@@ -1148,3 +1150,64 @@ def extract_wrapped(decorated):
from types import FunctionType
closure = (c.cell_contents for c in decorated.__closure__)
return next((c for c in closure if isinstance(c, FunctionType)), None)
def addQualityTag(item, itemlist, data, patron):
defQualVideo = {
"CAM": "metodo di ripresa che indica video di bassa qualità",
"TS": "questo metodo di ripresa effettua la ripresa su un tre piedi. Qualità sufficiente.",
"TC": "abbreviazione di TeleCine. Il metodo di ripresa del film è basato su una macchina capace di riversare le Super-8, o 35mm. La qualità è superiore a quella offerta da CAM e TS.",
"R5": "la qualità video di un R5 è pari a quella di un dvd, può contenere anche sottotitoli. Se è presente la dicitura LINE.ITALIAN è in italiano, altrimenti sarà disponibile in una lingua asiatica o russa.",
"R6": "video proveniente dallAsia.",
"FS": "video a schermo pieno, cioè FullScreen, quindi con un rapporto di 4:3.",
"WS": "video WideScreen, cioè rapporto 16:9.",
"VHSSCR": "video estratto da una videocassetta VHS.",
"DVDRIP": "la fonte video proviene da un DVD, la qualità è buona.",
"DVDSCR": "la fonte video proviene da un DVD. Tali filmati, di solito, appartengono a copie promozionali.",
"HDTVRIP": "video copiato e registrato da televisori in HD e che, per questo, restituiscono una qualità eccellente.",
"PD": "video registrato da Tv satellitare, qualità accettabile.",
"TV": "video registrato da Tv satellitare, qualità accettabile.",
"SAT": "video registrato da Tv satellitare, qualità accettabile.",
"DVBRIP": "video registrato da Tv satellitare, qualità accettabile.",
"TVRIP": "ripping simile al SAT RIP, solo che, in questo caso, la qualità del vide può variare a seconda dei casi.",
"VHSRIP": "video registrato da videocassetta. Qualità variabile.",
"BRRIP": "indica che il video è stato preso da una fonte BluRay. Nella maggior parte dei casi, avremo un video ad alta definizione.",
"BDRIP": "indica che il video è stato preso da una fonte BluRay. Nella maggior parte dei casi, avremo un video ad alta definizione.",
"DTTRIP": "video registrato da un canale digitale terreste. Qualità sufficiente.",
"HQ": "video in alta qualità.",
"WEBRIP": "in questo caso, i film sono estratti da portali relativi a canali televisivi o di video sharing come YouTube. La qualità varia dallSD al 1080p.",
"WEB-DL": "si tratta di un 720p o 1080p reperiti dalla versione americana di iTunes americano. La qualità è paragonabile a quella di un BluRayRip e permette di fruire di episodi televisivi, senza il fastidioso bollo distintivo della rete che trasmette.",
"WEBDL": "si tratta di un 720p o 1080p reperiti dalla versione americana di iTunes americano. La qualità è paragonabile a quella di un BluRayRip e permette di fruire di episodi televisivi, senza il fastidioso bollo distintivo della rete che trasmette.",
"DLMux": "si tratta di un 720p o 1080p reperiti dalla versione americana di iTunes americano. La qualità è paragonabile a quella di un BluRayRip e permette di fruire di episodi televisivi, senza il fastidioso bollo distintivo della rete che trasmette.",
"DVD5": "il film è in formato DVD Single Layer, nel quale vengono mantenute tutte le caratteristiche del DVD originale: tra queste il menu multilingue, i sottotitoli e i contenuti speciali, se presenti. Il video è codificato nel formato DVD originale MPEG-2.",
"DVD9": "ha le stesse caratteristiche del DVD5, ma le dimensioni del file sono di un DVD Dual Layer (8,5 GB).",
}
defQualAudio = {
"MD": "laudio è stato registrato via microfono, quindi la qualità è scarsa.",
"DTS": "audio ricavato dai dischi DTS2, quindi la qualità audio è elevata.",
"LD": "laudio è stato registrato tramite jack collegato alla macchina da presa, pertanto di discreta qualità.",
"DD": "audio ricavato dai dischi DTS cinema. Laudio è di buona qualità, ma potreste riscontrare il fatto che non potrebbe essere più riproducibile.",
"AC3": "audio in Dolby Digital puo' variare da 2.0 a 5.1 canali in alta qualità.",
"MP3": "codec per compressione audio utilizzato MP3.",
}
qualityStr = scrapertools.find_single_match(data, patron).strip()
if PY3:
qualityStr = qualityStr.encode('ascii', 'ignore')
else:
qualityStr = qualityStr.decode('unicode_escape').encode('ascii', 'ignore')
if qualityStr:
try:
audio, video = qualityStr.split('.')
descr = typo(video + ': ', 'color kod') + defQualVideo.get(video.upper(), '') + '\n' +\
typo(audio + ': ', 'color kod') + defQualAudio.get(audio.upper(), '')
except:
descr = ''
itemlist.insert(0,
Item(channel=item.channel,
action="",
title=typo(qualityStr, '[] color kod bold'),
plot=descr,
folder=False))
else:
log('nessun tag qualità trovato')

View File

@@ -692,8 +692,8 @@ class Tvdb(object):
response.close()
except Exception as ex:
if isinstance(ex, urllib).HTTPError:
logger.debug("code es %s " % ex.code)
# if isinstance(ex, urllib).HTTPError:
logger.debug("code es %s " % ex.code)
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
logger.error("error en: %s" % message)
@@ -757,8 +757,8 @@ class Tvdb(object):
response.close()
except Exception as ex:
if isinstance(ex, urllib).HTTPError:
logger.debug("code es %s " % ex.code)
# if isinstance(ex, urllib.parse).HTTPError:
logger.debug("code es %s " % ex.code)
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
logger.error("error en: %s" % message)
@@ -846,8 +846,8 @@ class Tvdb(object):
response.close()
except Exception as ex:
if isinstance(ex, urllib).HTTPError:
logger.debug("code es %s " % ex.code)
# if isinstance(ex, urllib).HTTPError:
logger.debug("code es %s " % ex.code)
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
logger.error("error en: %s" % message)

View File

@@ -461,13 +461,14 @@ def save_tvshow(item, episodelist):
item.infoLabels['title'] = item.contentSerieName
item_tvshow = Item(title=item.contentSerieName, channel="videolibrary", action="get_seasons",
fanart=item.infoLabels['fanart'], thumbnail=item.infoLabels['thumbnail'],
infoLabels=item.infoLabels, path=path.replace(TVSHOWS_PATH, ""))
infoLabels=item.infoLabels, path=path.replace(TVSHOWS_PATH, ""), fulltitle=item.fulltitle)
item_tvshow.library_playcounts = {}
item_tvshow.library_urls = {item.channel: item.url}
else:
# Si existe tvshow.nfo, pero estamos añadiendo un nuevo canal actualizamos el listado de urls
head_nfo, item_tvshow = read_nfo(tvshow_path)
item_tvshow.fulltitle = item.fulltitle
item_tvshow.channel = "videolibrary"
item_tvshow.action = "get_seasons"
item_tvshow.library_urls[item.channel] = item.url