KoD 1.7.2
- corretto il playback in tutti i casi (torrent, autoplay, videoteca, libreria ecc..)\n- piccole migliorie prestazionali nella ricerca globale\n- fix trailer\n\n
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.7.1" provider-name="KoD Team">
|
||||
<addon id="plugin.video.kod" name="Kodi on Demand" version="1.7.2" provider-name="KoD Team">
|
||||
<requires>
|
||||
<!-- <import addon="script.module.libtorrent" optional="true"/> -->
|
||||
<import addon="metadata.themoviedb.org"/>
|
||||
@@ -27,9 +27,9 @@
|
||||
<screenshot>resources/media/screenshot-2.png</screenshot>
|
||||
<screenshot>resources/media/screenshot-3.png</screenshot>
|
||||
</assets>
|
||||
<news>- aggiunta opzione "vai a pagina" nel menu contestuale dell'item "successivo>"
|
||||
- riscritti canali mediaset e raiplay
|
||||
- migliorie varie, in particolare nell'ordinamento dei server
|
||||
<news>- corretto il playback in tutti i casi (torrent, autoplay, videoteca, libreria ecc..)
|
||||
- piccole migliorie prestazionali nella ricerca globale
|
||||
- fix trailer
|
||||
</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]
|
||||
|
||||
@@ -87,7 +87,7 @@ def peliculas(item):
|
||||
patron = r'<a href="(?P<url>[^"]+)"[^>]+>\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.*?)(?: Sub| sub| SUB|")'
|
||||
|
||||
if item.args == 'newest': item.action = 'findvideos'
|
||||
|
||||
|
||||
patronNext = '<li class="page-item disabled">(?:[^>]+>){4}<a class="page-link" href="([^"]+)'
|
||||
|
||||
def itemHook(item):
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import cloudscraper, json, copy, inspect
|
||||
from core import jsontools, support, httptools, filetools
|
||||
from core import support
|
||||
from platformcode import autorenumber, logger
|
||||
import re
|
||||
import xbmc
|
||||
|
||||
|
||||
session = cloudscraper.create_scraper()
|
||||
|
||||
@@ -132,7 +129,8 @@ def news(item):
|
||||
fulltitle=it['anime']['title'],
|
||||
thumbnail=it['anime']['imageurl'],
|
||||
forcethumb = True,
|
||||
video_url=it['scws_id'],
|
||||
scws_id=it.get('scws_id', ''),
|
||||
video_url=it.get('link', ''),
|
||||
plot=it['anime']['plot'],
|
||||
action='findvideos')
|
||||
)
|
||||
@@ -157,7 +155,6 @@ def peliculas(item):
|
||||
records = session.post(host + '/archivio/get-animes', headers=headers, data=payload).json()['records']
|
||||
|
||||
for it in records:
|
||||
# logger.debug(jsontools.dump(it))
|
||||
lang = support.match(it['title'], patron=r'\(([It][Tt][Aa])\)').match
|
||||
title = support.re.sub(r'\s*\([^\)]+\)', '', it['title'])
|
||||
|
||||
@@ -176,15 +173,15 @@ def peliculas(item):
|
||||
itm.fulltitle = itm.show = itm.contentTitle = title
|
||||
itm.contentSerieName = ''
|
||||
itm.action = 'findvideos'
|
||||
itm.video_url = it['episodes'][0]['scws_id']
|
||||
itm.scws_id = it['episodes'][0].get('scws_id', '')
|
||||
itm.video_url = it['episodes'][0].get('link', '')
|
||||
|
||||
else:
|
||||
itm.contentType = 'tvshow'
|
||||
itm.contentTitle = ''
|
||||
itm.fulltitle = itm.show = itm.contentSerieName = title
|
||||
itm.action = 'episodios'
|
||||
itm.episodes = it['episodes'] if 'episodes' in it else it['scws_id']
|
||||
itm.video_url = item.url
|
||||
itm.episodes = it['episodes'] if 'episodes' in it else it.get('scws_id', '')
|
||||
|
||||
itemlist.append(itm)
|
||||
|
||||
@@ -210,8 +207,8 @@ def episodios(item):
|
||||
plot=item.plot,
|
||||
action='findvideos',
|
||||
contentType='episode',
|
||||
scws_id=it['scws_id'],
|
||||
video_url=it['link']))
|
||||
scws_id=it.get('scws_id', ''),
|
||||
video_url=it.get('link', '')))
|
||||
|
||||
if inspect.stack()[1][3] not in ['find_episodes']:
|
||||
autorenumber.start(itemlist, item)
|
||||
@@ -221,17 +218,17 @@ def episodios(item):
|
||||
|
||||
|
||||
def findvideos(item):
|
||||
if item.scvs_id:
|
||||
if item.scws_id:
|
||||
from time import time
|
||||
from base64 import b64encode
|
||||
from hashlib import md5
|
||||
|
||||
# Calculate Token
|
||||
client_ip = support.httptools.downloadpage('https://scws.xyz/videos/{}'.format(item.scvs_id), headers=headers).json.get('client_ip')
|
||||
client_ip = support.httptools.downloadpage('https://scws.xyz/videos/{}'.format(item.scws_id), headers=headers).json.get('client_ip')
|
||||
expires = int(time() + 172800)
|
||||
token = b64encode(md5('{}{} Yc8U6r8KjAKAepEA'.format(expires, client_ip).encode('utf-8')).digest()).decode('utf-8').replace('=', '').replace('+', '-').replace('/', '_')
|
||||
|
||||
url = 'https://scws.xyz/master/{}?token={}&expires={}&n=1'.format(item.scvs_id, token, expires)
|
||||
url = 'https://scws.xyz/master/{}?token={}&expires={}&n=1'.format(item.scws_id, token, expires)
|
||||
itemlist = [item.clone(title=support.config.get_localized_string(30137), url=url, server='directo', action='play', manifest='hls')]
|
||||
else:
|
||||
itemlist = [item.clone(title=support.config.get_localized_string(30137), url=item.video_url, server='directo', action='play')]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# by Greko
|
||||
# ------------------------------------------------------------
|
||||
|
||||
from core import httptools, support
|
||||
from core import support
|
||||
from core.item import Item
|
||||
|
||||
# def findhost(url):
|
||||
@@ -99,4 +99,10 @@ def newest(categoria):
|
||||
|
||||
def findvideos(item):
|
||||
support.info()
|
||||
return support.server(item, item.other)
|
||||
itemlist = support.server(item, item.other)
|
||||
# testo che tutti i link siano stati risolti
|
||||
if support.logger.testMode:
|
||||
if len(itemlist) < len(support.match(item.other, patron='<a href="([^"]+)').matches):
|
||||
raise Exception('Manca qualche server')
|
||||
return itemlist
|
||||
|
||||
|
||||
@@ -53,10 +53,11 @@ def peliculas(item):
|
||||
patron = r'>(?P<quality>[^"<]+)'
|
||||
patron += '<TD[^>]+><A class="tab" HREF="(?P<url>[^"]+)"\s*>[^<]+<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<size>[^<]+)<[^>]+>[^>]+>[^>]+><form action="[^"]+/\d+/(?P<title>[^"]+)[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<seed>[^<]+)'
|
||||
|
||||
if not sceneTitle:
|
||||
def itemHook(item):
|
||||
def itemHook(item):
|
||||
if not sceneTitle:
|
||||
item.title = item.title.replace('_', ' ')
|
||||
return item
|
||||
item.title = support.scrapertools.decodeHtmlentities(support.urlparse.unquote(item.title))
|
||||
return item
|
||||
|
||||
if 'search' not in item.args:
|
||||
item.url += str(item.args[0])
|
||||
|
||||
@@ -184,9 +184,16 @@ def findvideos(item):
|
||||
logger.info(episode)
|
||||
if episode['video_id'] == item.video_id:
|
||||
url = vvvvid_decoder.dec_ei(episode['embed_info'] or episode['embed_info_sd'])
|
||||
if 'youtube' in url: item.url = url
|
||||
# if 'youtube' in url: item.url = url
|
||||
item.url = url.replace('manifest.f4m','master.m3u8').replace('http://','https://').replace('/z/','/i/')
|
||||
if 'https' not in item.url:
|
||||
if 'youtube' in url:
|
||||
itemlist.append(
|
||||
item.clone(action= 'play',
|
||||
title= 'YouTube',
|
||||
url= item.url,
|
||||
server= 'youtube')
|
||||
)
|
||||
elif 'https' not in item.url:
|
||||
url = support.match('https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/playlist.m3u').data
|
||||
url = url.split()[-1]
|
||||
itemlist.append(
|
||||
|
||||
@@ -40,9 +40,11 @@ def start(itemlist, item):
|
||||
return itemlist
|
||||
|
||||
import xbmc
|
||||
control_item = Item().fromurl(xbmc.getInfoLabel('Container.FolderPath'))
|
||||
if control_item.action == item.action:
|
||||
return itemlist
|
||||
control_info = xbmc.getInfoLabel('Container.FolderPath')
|
||||
if control_info:
|
||||
control_item = Item().fromurl(control_info)
|
||||
if control_item.action == item.action:
|
||||
return itemlist
|
||||
|
||||
if config.get_setting('autoplay') or item.autoplay:
|
||||
# Save the current value of "Action and Player Mode" in preferences
|
||||
|
||||
@@ -52,7 +52,7 @@ directIP = {
|
||||
}
|
||||
|
||||
# Maximum wait time for downloadpage, if nothing is specified
|
||||
HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = config.get_setting('httptools_timeout', default=15)
|
||||
HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = config.get_setting('httptools_timeout', default=5)
|
||||
if HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT == 0: HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = None
|
||||
|
||||
# Random use of User-Agents, if nad is not specified
|
||||
|
||||
@@ -490,7 +490,7 @@ def title_unify(title):
|
||||
if cat != 'Mn':
|
||||
if cat == 'Pd':
|
||||
c_new = '-'
|
||||
elif cat in ['Ll', 'Lu'] or c == ':':
|
||||
elif cat in ['Ll', 'Lu', 'Nd'] or c == ':':
|
||||
c_new = c
|
||||
else:
|
||||
c_new = ' '
|
||||
|
||||
@@ -597,6 +597,7 @@ def scrape(func):
|
||||
nextArgs['item'] = item
|
||||
itemlist = newFunc()
|
||||
itemlist = [i for i in itemlist if i.action not in ['add_pelicula_to_library', 'add_serie_to_library']]
|
||||
logger.debug(item.channel + ' scraping time ' + ':', time()-scrapingTime)
|
||||
|
||||
if anime and inspect.stack()[1][3] not in ['find_episodes']:
|
||||
from platformcode import autorenumber
|
||||
@@ -655,7 +656,6 @@ def scrape(func):
|
||||
if config.get_setting('trakt_sync'):
|
||||
from core import trakt_tools
|
||||
trakt_tools.trakt_check(itemlist)
|
||||
logger.debug('scraping time: ', time()-scrapingTime)
|
||||
return itemlist
|
||||
|
||||
return wrapper
|
||||
@@ -1267,6 +1267,8 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
|
||||
findS = servertools.get_server_from_url(videoitem.url)
|
||||
if not findS:
|
||||
info(videoitem, 'Non supportato')
|
||||
if logger.testMode:
|
||||
raise Exception('Server missing: ' + videoitem.url)
|
||||
return
|
||||
videoitem.server = findS[2]
|
||||
videoitem.title = findS[0]
|
||||
|
||||
@@ -41,7 +41,7 @@ def read_nfo(path_nfo, item=None):
|
||||
@rtype: tuple (str, Item)
|
||||
"""
|
||||
head_nfo = ""
|
||||
it = None
|
||||
it = Item()
|
||||
|
||||
data = filetools.read(path_nfo)
|
||||
|
||||
@@ -277,7 +277,7 @@ def filter_list(episodelist, action=None, path=None):
|
||||
channel_prefs = {}
|
||||
lang_sel = quality_sel = show_title = channel =''
|
||||
|
||||
if action:
|
||||
if action:
|
||||
tvshow_path = filetools.join(path, "tvshow.nfo")
|
||||
head_nfo, tvshow_item = read_nfo(tvshow_path)
|
||||
channel = episodelist[0].channel
|
||||
@@ -577,7 +577,8 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
@return: the number of failed episodes
|
||||
"""
|
||||
logger.debug()
|
||||
episodelist = filter_list(episodelist, serie.action, path)
|
||||
if episodelist:
|
||||
episodelist = filter_list(episodelist, serie.action, path)
|
||||
# No episode list, nothing to save
|
||||
if not len(episodelist):
|
||||
logger.debug("There is no episode list, we go out without creating strm")
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
# Use of this source code is governed by the 3-clause BSD license
|
||||
# that can be found in the LICENSE file.
|
||||
#
|
||||
__title__ = 'babelfish'
|
||||
__version__ = '0.5.5-dev'
|
||||
__author__ = 'Antoine Bertin'
|
||||
__license__ = 'BSD'
|
||||
__copyright__ = 'Copyright 2015 the BabelFish authors'
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
|
||||
@@ -2,20 +2,22 @@
|
||||
# Use of this source code is governed by the 3-clause BSD license
|
||||
# that can be found in the LICENSE file.
|
||||
#
|
||||
import collections
|
||||
import functools
|
||||
from importlib import import_module
|
||||
|
||||
# from pkg_resources import iter_entry_points, EntryPoint
|
||||
from ..exceptions import LanguageConvertError, LanguageReverseError
|
||||
|
||||
try:
|
||||
# Python 3.3+
|
||||
from collections.abc import Mapping, MutableMapping
|
||||
except ImportError:
|
||||
from collections import Mapping, MutableMapping
|
||||
from importlib import import_module
|
||||
|
||||
# from https://github.com/kennethreitz/requests/blob/master/requests/structures.py
|
||||
class CaseInsensitiveDict(collections.MutableMapping):
|
||||
class CaseInsensitiveDict(MutableMapping):
|
||||
"""A case-insensitive ``dict``-like object.
|
||||
|
||||
Implements all methods and operations of
|
||||
``collections.MutableMapping`` as well as dict's ``copy``. Also
|
||||
``collections.abc.MutableMapping`` as well as dict's ``copy``. Also
|
||||
provides ``lower_items``.
|
||||
|
||||
All keys are expected to be strings. The structure remembers the
|
||||
@@ -66,7 +68,7 @@ class CaseInsensitiveDict(collections.MutableMapping):
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, collections.Mapping):
|
||||
if isinstance(other, Mapping):
|
||||
other = CaseInsensitiveDict(other)
|
||||
else:
|
||||
return NotImplemented
|
||||
@@ -242,6 +244,7 @@ class ConverterManager(object):
|
||||
# if ep.name == name:
|
||||
# self.converters[ep.name] = ep.load()()
|
||||
# return self.converters[ep.name]
|
||||
|
||||
def parse(str):
|
||||
import re
|
||||
match = re.match('(?P<name>\w+) = (?P<module>[a-z0-9.]+):(?P<class>\w+)', str)
|
||||
|
||||
@@ -14,10 +14,10 @@ class OpenSubtitlesConverter(LanguageReverseConverter):
|
||||
def __init__(self):
|
||||
self.alpha3b_converter = language_converters['alpha3b']
|
||||
self.alpha2_converter = language_converters['alpha2']
|
||||
self.to_opensubtitles = {('por', 'BR'): 'pob', ('gre', None): 'ell', ('srp', None): 'scc', ('srp', 'ME'): 'mne'}
|
||||
self.to_opensubtitles = {('por', 'BR'): 'pob', ('gre', None): 'ell', ('srp', None): 'scc', ('srp', 'ME'): 'mne', ('chi', 'TW'): 'zht'}
|
||||
self.from_opensubtitles = CaseInsensitiveDict({'pob': ('por', 'BR'), 'pb': ('por', 'BR'), 'ell': ('ell', None),
|
||||
'scc': ('srp', None), 'mne': ('srp', 'ME')})
|
||||
self.codes = (self.alpha2_converter.codes | self.alpha3b_converter.codes | set(['pob', 'pb', 'scc', 'mne']))
|
||||
'scc': ('srp', None), 'mne': ('srp', 'ME'), 'zht': ('zho', 'TW')})
|
||||
self.codes = (self.alpha2_converter.codes | self.alpha3b_converter.codes | set(self.from_opensubtitles.keys()))
|
||||
|
||||
def convert(self, alpha3, country=None, script=None):
|
||||
alpha3b = self.alpha3b_converter.convert(alpha3, country, script)
|
||||
|
||||
@@ -8,9 +8,9 @@ from __future__ import unicode_literals
|
||||
from collections import namedtuple
|
||||
from functools import partial
|
||||
# from pkg_resources import resource_stream # @UnresolvedImport
|
||||
import os, io
|
||||
from .converters import ConverterManager
|
||||
from . import basestr
|
||||
import os, io
|
||||
|
||||
|
||||
COUNTRIES = {}
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
from __future__ import unicode_literals
|
||||
from collections import namedtuple
|
||||
from functools import partial
|
||||
import os, io
|
||||
# from pkg_resources import resource_stream # @UnresolvedImport
|
||||
from .converters import ConverterManager
|
||||
from .country import Country
|
||||
from .exceptions import LanguageConvertError
|
||||
from .script import Script
|
||||
from . import basestr
|
||||
import os, io
|
||||
|
||||
|
||||
LANGUAGES = set()
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
# that can be found in the LICENSE file.
|
||||
#
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os, io
|
||||
from collections import namedtuple
|
||||
# from pkg_resources import resource_stream # @UnresolvedImport
|
||||
from . import basestr
|
||||
import os, io
|
||||
|
||||
#: Script code to script name mapping
|
||||
SCRIPTS = {}
|
||||
|
||||
@@ -38,7 +38,7 @@ def query(name, type='A', server=DOH_SERVER, path="/dns-query", fallback=True):
|
||||
|
||||
try:
|
||||
req = _Request("https://%s%s?name=%s&type=%s" % (server, path, name, type), headers={"Accept": "application/dns-json"})
|
||||
content = _urlopen(req).read().decode()
|
||||
content = _urlopen(req, timeout=2).read().decode()
|
||||
reply = json.loads(content)
|
||||
|
||||
if "Answer" in reply:
|
||||
|
||||
@@ -38,6 +38,9 @@ from threading import Thread
|
||||
|
||||
__version__ = '1.7.0.dev0'
|
||||
|
||||
import xbmc
|
||||
kodi_monitor = xbmc.Monitor()
|
||||
|
||||
major_version = sys.version_info[0]
|
||||
if major_version < 3: # py <= 2.x
|
||||
if sys.version_info[1] < 5: # py <= 2.4
|
||||
@@ -172,6 +175,7 @@ class SqliteDict(DictClass):
|
||||
self.encode = encode
|
||||
self.decode = decode
|
||||
self.timeout = timeout
|
||||
self.cache = {}
|
||||
|
||||
logger.info("opening Sqlite table %r in %r" % (tablename, filename))
|
||||
self.conn = self._new_conn()
|
||||
@@ -234,7 +238,9 @@ class SqliteDict(DictClass):
|
||||
def iteritems(self):
|
||||
GET_ITEMS = 'SELECT key, value FROM "%s" ORDER BY rowid' % self.tablename
|
||||
for key, value in self.conn.select(GET_ITEMS):
|
||||
yield key, self.decode(value)
|
||||
ret = key, self.decode(value)
|
||||
self.cache[key] = ret[1]
|
||||
yield ret
|
||||
|
||||
def keys(self):
|
||||
return self.iterkeys() if major_version > 2 else list(self.iterkeys())
|
||||
@@ -250,11 +256,15 @@ class SqliteDict(DictClass):
|
||||
return self.conn.select_one(HAS_ITEM, (key,)) is not None
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key in self.cache.keys():
|
||||
return self.cache[key]
|
||||
GET_ITEM = 'SELECT value FROM "%s" WHERE key = ?' % self.tablename
|
||||
item = self.conn.select_one(GET_ITEM, (key,))
|
||||
if item is None:
|
||||
raise KeyError(key)
|
||||
return self.decode(item[0])
|
||||
ret = self.decode(item[0])
|
||||
self.cache[key] = ret
|
||||
return ret
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if self.flag == 'r':
|
||||
@@ -264,6 +274,7 @@ class SqliteDict(DictClass):
|
||||
self.conn.execute(ADD_ITEM, (key, self.encode(value)))
|
||||
if self.autocommit:
|
||||
self.commit()
|
||||
self.cache[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
if self.flag == 'r':
|
||||
@@ -275,6 +286,7 @@ class SqliteDict(DictClass):
|
||||
self.conn.execute(DEL_ITEM, (key,))
|
||||
if self.autocommit:
|
||||
self.commit()
|
||||
del self.cache[key]
|
||||
|
||||
def update(self, items=(), **kwds):
|
||||
if self.flag == 'r':
|
||||
@@ -292,6 +304,7 @@ class SqliteDict(DictClass):
|
||||
self.update(kwds)
|
||||
if self.autocommit:
|
||||
self.commit()
|
||||
self.cache.update(items)
|
||||
|
||||
def __iter__(self):
|
||||
return self.iterkeys()
|
||||
@@ -305,6 +318,7 @@ class SqliteDict(DictClass):
|
||||
self.conn.commit()
|
||||
self.conn.execute(CLEAR_ALL)
|
||||
self.conn.commit()
|
||||
self.cache = {}
|
||||
|
||||
@staticmethod
|
||||
def get_tablenames(filename):
|
||||
@@ -403,6 +417,7 @@ class SqliteMultithread(Thread):
|
||||
self.log = logging.getLogger('sqlitedict.SqliteMultithread')
|
||||
self.start()
|
||||
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
if self.autocommit:
|
||||
@@ -428,7 +443,7 @@ class SqliteMultithread(Thread):
|
||||
self._sqlitedict_thread_initialized = True
|
||||
|
||||
res = None
|
||||
while True:
|
||||
while not kodi_monitor.abortRequested():
|
||||
req, arg, res, outer_stack = self.reqs.get()
|
||||
if req == '--close--':
|
||||
assert res, ('--close-- without return queue', res)
|
||||
|
||||
@@ -60,6 +60,7 @@ class UnshortenIt(object):
|
||||
|
||||
def unshorten(self, uri, type=None):
|
||||
code = 0
|
||||
originalUri = uri
|
||||
while True:
|
||||
uri = uri.strip()
|
||||
oldUri = uri
|
||||
@@ -114,6 +115,8 @@ class UnshortenIt(object):
|
||||
|
||||
logger.info(uri)
|
||||
|
||||
if originalUri == uri and logger.testMode:
|
||||
raise Exception('Not un-shortened link: ' + uri)
|
||||
return uri, code
|
||||
|
||||
def unwrap_30x(self, uri, timeout=10):
|
||||
|
||||
@@ -52,6 +52,7 @@ def download(item=None):
|
||||
ret = False
|
||||
else:
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
|
||||
def extract():
|
||||
|
||||
@@ -470,12 +470,10 @@ def play_from_library(item):
|
||||
|
||||
# logger.debug("item: \n" + item.tostring('\n'))
|
||||
# xbmc.Player().play(os.path.join(config.get_runtime_path(), "resources", "kod.mp4"))
|
||||
if not item.autoplay:
|
||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4")))
|
||||
while not platformtools.is_playing():
|
||||
xbmc.sleep(10)
|
||||
xbmc.Player().stop()
|
||||
platformtools.prevent_busy()
|
||||
if not item.autoplay and not item.next_ep:
|
||||
platformtools.fakeVideo()
|
||||
# from core.support import dbg;dbg()
|
||||
# platformtools.prevent_busy(item)
|
||||
|
||||
|
||||
itemlist=[]
|
||||
@@ -553,5 +551,6 @@ def play_from_library(item):
|
||||
item = videolibrary.play(itemlist[selection + selection_implementation])[0]
|
||||
platformtools.play_video(item)
|
||||
reopen = True
|
||||
if item.server == 'torrent': return
|
||||
# if (platformtools.is_playing() and item.action) or item.server == 'torrent' or config.get_setting('autoplay'): break
|
||||
|
||||
|
||||
@@ -395,7 +395,6 @@ def viewmodeMonitor():
|
||||
currentModeName = xbmc.getInfoLabel('Container.Viewmode')
|
||||
parent_info = xbmc.getInfoLabel('Container.FolderPath')
|
||||
item_info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath')
|
||||
parent_item = Item().fromurl(parent_info)
|
||||
win = xbmcgui.Window(10025)
|
||||
currentMode = int(win.getFocusId())
|
||||
# logger.debug('CM', currentMode, 'CN',currentModeName, 'label',xbmc.getInfoLabel('Container.FolderPath'))
|
||||
@@ -1386,7 +1385,7 @@ def set_player(item, xlistitem, mediaurl, view, strm):
|
||||
logger.info("mediaurl=" + mediaurl)
|
||||
|
||||
if player_mode in [0,1]:
|
||||
prevent_busy()
|
||||
prevent_busy(item)
|
||||
if player_mode in [1]:
|
||||
item.played_time = resume_playback(get_played_time(item))
|
||||
|
||||
@@ -1422,8 +1421,9 @@ def set_player(item, xlistitem, mediaurl, view, strm):
|
||||
# if it is a video library file send to mark as seen
|
||||
if strm or item.strm_path: item.options['strm'] = True
|
||||
# if player_mode == 1: item.options['continue'] = True
|
||||
from platformcode import xbmc_videolibrary
|
||||
xbmc_videolibrary.mark_auto_as_watched(item)
|
||||
if not mediaurl.startswith('plugin'):
|
||||
from platformcode import xbmc_videolibrary
|
||||
xbmc_videolibrary.mark_auto_as_watched(item)
|
||||
|
||||
# for cases where the audio playback window appears in place of the video one
|
||||
if item.focusOnVideoPlayer:
|
||||
@@ -1473,7 +1473,6 @@ def torrent_client_installed(show_tuple=False):
|
||||
|
||||
def play_torrent(item, xlistitem, mediaurl):
|
||||
logger.debug()
|
||||
import time
|
||||
from servers import torrent
|
||||
|
||||
torrent_options = torrent_client_installed(show_tuple=True)
|
||||
@@ -1482,7 +1481,7 @@ def play_torrent(item, xlistitem, mediaurl):
|
||||
install = elementum_download.download()
|
||||
if install:
|
||||
return play_torrent(item, xlistitem, mediaurl)
|
||||
else:
|
||||
else:
|
||||
selection = -1
|
||||
elif len(torrent_options) > 1:
|
||||
selection = dialog_select(config.get_localized_string(70193), [opcion[0] for opcion in torrent_options])
|
||||
@@ -1503,14 +1502,18 @@ def play_torrent(item, xlistitem, mediaurl):
|
||||
|
||||
if torr_client in ['elementum'] and item.downloadFilename:
|
||||
torrent.elementum_download(item)
|
||||
|
||||
else:
|
||||
if item.fromLibrary and item.play_from == 'window':
|
||||
# xbmc.executebuiltin("PlayMedia(" + torrent_options[selection][1] % mediaurl + ")")
|
||||
if (item.fromLibrary and item.play_from == 'window') or item.window:
|
||||
xlistitem.setPath(torrent_options[selection][1] % mediaurl)
|
||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||
playlist.clear()
|
||||
playlist.add(torrent_options[selection][1] % mediaurl, xlistitem)
|
||||
xbmc_player.play(playlist, xlistitem)
|
||||
else:
|
||||
if not item.autoplay and item.channel != 'videolibrary': fakeVideo()
|
||||
if xbmc.getCondVisibility("system.platform.android"): xbmc.sleep(3000)
|
||||
xbmc.executebuiltin("PlayMedia(" + torrent_options[selection][1] % mediaurl + ")")
|
||||
|
||||
# torrent.mark_auto_as_watched(item)
|
||||
@@ -1820,5 +1823,15 @@ def set_played_time(item):
|
||||
del db['viewed'][ID]
|
||||
|
||||
|
||||
def prevent_busy():
|
||||
xbmc.executebuiltin('Dialog.Close(all,true)')
|
||||
def prevent_busy(item=None):
|
||||
if item and (not item.autoplay and item.channel != 'videolibrary' and not item.window):
|
||||
fakeVideo()
|
||||
else:
|
||||
xbmc.executebuiltin('Dialog.Close(all,true)')
|
||||
|
||||
|
||||
def fakeVideo():
|
||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4")))
|
||||
while not is_playing():
|
||||
xbmc.sleep(10)
|
||||
xbmc.Player().stop()
|
||||
@@ -100,7 +100,7 @@ def mark_auto_as_watched(item):
|
||||
xbmc.sleep(700)
|
||||
xbmc.executebuiltin('Action(ParentDir)')
|
||||
xbmc.sleep(500)
|
||||
# from core.support import dbg;dbg()
|
||||
|
||||
if next_episode and next_episode.next_ep and config.get_setting('next_ep') < 3:
|
||||
from platformcode.launcher import run
|
||||
run(next_episode)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<setting id="resolve_priority" type="select" label="70110" lvalues="70164|70165|70166" default="0"/>
|
||||
<setting id="resolve_stop" type="bool" label="70111" default="true"/>
|
||||
<setting id="hidepremium" type="bool" label="70112" default="false"/>
|
||||
<setting id="httptools_timeout" type="slider" option="int" range="0,5,120" label="70580" default="15"/>
|
||||
<setting id="httptools_timeout" type="slider" option="int" range="0,1,30" label="70580" default="5"/>
|
||||
<setting label="70145" type="lsep"/>
|
||||
<setting id="favorites_servers" type="bool" label="60551" default="false" visible="false"/>
|
||||
<setting id="quality_priority" type="bool" label="30069" default="false" visible="false"/>
|
||||
@@ -151,7 +151,7 @@
|
||||
<setting label="30024" type="lsep"/>
|
||||
<setting id="quick_menu" type="bool" label="60360" default="true"/>
|
||||
<!-- <setting id="side_menu" type="bool" label="70737" default="false"/> -->
|
||||
<!-- <setting id="kod_menu" type="bool" label="60026" default="true"/>-->
|
||||
<!-- <setting id="kod_menu" type="bool" label="60026" default="true"/>-->
|
||||
<setting id="infoplus" type="bool" label="70151" default="false"/>
|
||||
<!-- <setting id="infoplus_set" type="bool" label="70128" visible="eq(-1,true)" default="false" subsetting="true"/> -->
|
||||
<!-- <setting id="extended_info" type="bool" label="70152" default="false"/> -->
|
||||
|
||||
@@ -122,7 +122,7 @@ def check_for_update(overwrite=True):
|
||||
estado_verify_playcount_series = False
|
||||
|
||||
try:
|
||||
if config.get_setting("update", "videolibrary") != 0 or overwrite:
|
||||
if overwrite or (config.get_setting("update", "videolibrary") != 0 and hoy.strftime('%Y-%m-%d') != config.get_setting('updatelibrary_last_check', 'videolibrary')):
|
||||
config.set_setting("updatelibrary_last_check", hoy.strftime('%Y-%m-%d'), "videolibrary")
|
||||
|
||||
heading = config.get_localized_string(60601)
|
||||
|
||||
@@ -395,8 +395,10 @@ class SearchWindow(xbmcgui.WindowXML):
|
||||
if self.exit: return
|
||||
# some channels may use original title
|
||||
if self.item.mode != 'all' and not valid and self.item.infoLabels.get('originaltitle'):
|
||||
logger.debug('retring with original title on channel ' + channel)
|
||||
dummy, valid, dummy = search(self.item.infoLabels.get('originaltitle'))
|
||||
original = scrapertools.title_unify(self.item.infoLabels.get('originaltitle'))
|
||||
if self.item.text != original:
|
||||
logger.debug('retring with original title on channel ' + channel)
|
||||
dummy, valid, dummy = search(original)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
@@ -93,15 +93,16 @@ def buscartrailer(item, trailers=[]):
|
||||
if item.infoLabels['trailer'] and not trailers:
|
||||
url = item.infoLabels['trailer']
|
||||
if "youtube" in url:
|
||||
url = url.replace("embed/", "watch?v=")
|
||||
title, url, server = servertools.findvideos(url)[0]
|
||||
url = url.replace("embed/", "watch?v=").replace('plugin://plugin.video.youtube/play/?video_id=', 'https://www.youtube.com/watch?v=')
|
||||
finded = servertools.findvideos(url)[0]
|
||||
title = finded[0]
|
||||
url = finded[1]
|
||||
server = finded[2]
|
||||
title = "Trailer [" + server + "]"
|
||||
itemlist.append(item.clone(title=title, url=url, server=server, action="play"))
|
||||
try:
|
||||
for trailer in trailers:
|
||||
title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en",
|
||||
"ING").replace(
|
||||
"it", "ITA") + ") [tmdb/youtube]"
|
||||
title = trailer['name'] + " [" + trailer['size'] + "p] (" + trailer['language'].replace("en", "ING").replace( "it", "ITA") + ") [tmdb/youtube]"
|
||||
itemlist.append(item.clone(action="play", title=title, url=trailer['url'], server="youtube"))
|
||||
except:
|
||||
import traceback
|
||||
@@ -175,10 +176,11 @@ def tmdb_trailers(item, dialog, tipo="movie"):
|
||||
for vid in tmdb_search.get_videos():
|
||||
if vid['type'].lower() == 'trailer':
|
||||
title = vid['name']
|
||||
it = del_id(item.clone(action="play", title=title, title2="TMDB(youtube) - " + vid['language'].replace("en", "ING").replace("it", "ITA") + " [" + vid['size'] + "p]", url=vid['url'], server="youtube"))
|
||||
it = del_id(item.clone(action="play", title=title, title2="TMDB(youtube) - " + vid['language'].replace("en", "ING").replace("it", "ITA") + " [" + vid['size'] + "p]", url=vid['url'], server="youtube", window=True))
|
||||
itemlist.append(it)
|
||||
|
||||
if vid['language'] == def_lang and not found: # play now because lang is correct and TMDB is trusted
|
||||
logger.debug('TMDB PLAY ITEM', it)
|
||||
found = True
|
||||
launcher.run(it)
|
||||
dialog.close()
|
||||
@@ -214,7 +216,7 @@ def youtube_search(item):
|
||||
scrapedtitle = "%s" % scrapedtitle
|
||||
url = urlparse.urljoin('https://www.youtube.com/', scrapedurl)
|
||||
itemlist.append(del_id(item.clone(title=scrapedtitle, title2='Youtube - ' + scrapedduration, action="play", server="youtube",
|
||||
url=url, thumbnail=scrapedthumbnail)))
|
||||
url=url, thumbnail=scrapedthumbnail, window=True)))
|
||||
# next_page = scrapertools.find_single_match(data, '<a href="([^"]+)"[^>]+><span class="yt-uix-button-content">')
|
||||
# if next_page != "":
|
||||
# next_page = urlparse.urljoin("https://www.youtube.com", next_page)
|
||||
@@ -250,7 +252,7 @@ def search_links_mymovies(item):
|
||||
logger.debug()
|
||||
trailer_url = match(item, patron=r'<source src="([^"]+)').match
|
||||
if trailer_url:
|
||||
it = del_id(item.clone(url=trailer_url, server='directo', action="play"))
|
||||
it = del_id(item.clone(url=trailer_url, server='directo', action="play", window=True))
|
||||
return it
|
||||
|
||||
|
||||
@@ -274,10 +276,10 @@ try:
|
||||
def onInit(self):
|
||||
try:
|
||||
self.control_list = self.getControl(6)
|
||||
self.getControl(5).setNavigation(self.control_list, self.control_list, self.control_list,
|
||||
self.control_list)
|
||||
self.getControl(3).setEnabled(0)
|
||||
self.getControl(3).setVisible(0)
|
||||
self.getControl(5).setNavigation(self.getControl(7), self.getControl(7), self.control_list, self.control_list)
|
||||
self.getControl(7).setNavigation(self.getControl(5), self.getControl(5), self.control_list, self.control_list)
|
||||
self.getControl(8).setEnabled(0)
|
||||
self.getControl(8).setVisible(0)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -309,7 +311,7 @@ try:
|
||||
|
||||
def onAction(self, action):
|
||||
global window_select, result
|
||||
if action == 92 or action == 110:
|
||||
if action in [92, 110, 10]:
|
||||
result = "no_video"
|
||||
self.close()
|
||||
window_select.pop()
|
||||
@@ -318,8 +320,9 @@ try:
|
||||
del window_select
|
||||
else:
|
||||
window_select[-1].doModal()
|
||||
|
||||
try:
|
||||
if (action == 7 or action == 100) and self.getFocusId() == 6:
|
||||
if action in [7, 100] and self.getFocusId() == 6:
|
||||
selectitem = self.control_list.getSelectedItem()
|
||||
item = Item().fromurl(selectitem.getProperty("item_copy"))
|
||||
if item.action == "play" and self.item.windowed:
|
||||
@@ -335,10 +338,12 @@ try:
|
||||
window.close()
|
||||
retorna = platformtools.play_video(item, force_direct=True)
|
||||
if not retorna:
|
||||
while True:
|
||||
xbmc.sleep(1000)
|
||||
if not xbmc.Player().isPlaying():
|
||||
break
|
||||
while not xbmc.Player().isPlaying():
|
||||
xbmc.sleep(10)
|
||||
while xbmc.Player().isPlaying():
|
||||
xbmc.sleep(100)
|
||||
# if not xbmc.Player().isPlaying():
|
||||
# break
|
||||
window_select[-1].doModal()
|
||||
else:
|
||||
self.close()
|
||||
|
||||
@@ -96,6 +96,7 @@ def get_results(nfo_path, root, Type, local=False):
|
||||
|
||||
if filetools.exists(nfo_path):
|
||||
head_nfo, item = videolibrarytools.read_nfo(nfo_path)
|
||||
item.contentType = Type
|
||||
|
||||
# If you have not read the .nfo well, we will proceed to the next
|
||||
if not item:
|
||||
@@ -246,7 +247,7 @@ def get_seasons(item):
|
||||
# We create one item for each season
|
||||
for season, title in list(dict_temp.items()):
|
||||
new_item = item.clone(action="get_episodes", title=title, contentSeason=season,
|
||||
filtrar_season=True, channel='videolibrary')
|
||||
filtrar_season=True, channel='videolibrary', contentType='season')
|
||||
|
||||
#Contextual menu: Mark the season as viewed or not
|
||||
visto = item_nfo.library_playcounts.get("season %s" % season, 0)
|
||||
@@ -313,6 +314,7 @@ def get_episodes(item):
|
||||
|
||||
epi.contentTitle = "%sx%s" % (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2))
|
||||
epi.title = "%sx%s - %s" % (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2), title_episodie)
|
||||
epi.contentType = 'episode'
|
||||
|
||||
if item_nfo.library_filter_show:
|
||||
epi.library_filter_show = item_nfo.library_filter_show
|
||||
|
||||
@@ -74,10 +74,6 @@ chNumRis = {
|
||||
'Film': 16,
|
||||
'Serie TV': 16,
|
||||
},
|
||||
'altadefinizionecommunity': {
|
||||
'Film': 22,
|
||||
'Serie TV': 22,
|
||||
},
|
||||
'altadefinizioneclick': {
|
||||
'Film': 36,
|
||||
'Serie TV': 36,
|
||||
@@ -163,6 +159,7 @@ for chItem in channel_list:
|
||||
error = None
|
||||
menuItemlist = {}
|
||||
serversFound = {}
|
||||
firstContent = None # to check search
|
||||
logMenu = {}
|
||||
|
||||
try:
|
||||
@@ -180,37 +177,48 @@ for chItem in channel_list:
|
||||
if it.action == 'channel_config':
|
||||
hasChannelConfig = True
|
||||
continue
|
||||
if it.action == 'search': # channel-specific
|
||||
continue
|
||||
menuItemlist[it.title] = []
|
||||
|
||||
itemlist = getattr(module, it.action)(it)
|
||||
menuItemlist[it.title] = itemlist
|
||||
if it.action == 'search':
|
||||
# no title to search
|
||||
if not firstContent:
|
||||
continue
|
||||
itemlist = module.search(it, firstContent)
|
||||
else:
|
||||
itemlist = getattr(module, it.action)(it)
|
||||
|
||||
# some sites might have no link inside, but if all results are without servers, there's something wrong
|
||||
for resIt in itemlist:
|
||||
if resIt.action == 'findvideos':
|
||||
if hasattr(module, resIt.action):
|
||||
serversFound[it.title] = getattr(module, resIt.action)(resIt)
|
||||
else:
|
||||
serversFound[it.title] = [resIt]
|
||||
if itemlist and itemlist[0].action in ('findvideos', 'episodios'):
|
||||
firstContent = re.match('[ \w]*', itemlist[0].fulltitle).group(0)
|
||||
|
||||
if serversFound[it.title]:
|
||||
if hasattr(module, 'play'):
|
||||
tmp = []
|
||||
# some sites might have no link inside, but if all results are without servers, there's something wrong
|
||||
for resIt in itemlist:
|
||||
if resIt.action == 'findvideos' or resIt.action == 'episodios':
|
||||
if hasattr(module, resIt.action):
|
||||
serversFound[it.title] = getattr(module, resIt.action)(resIt)
|
||||
if serversFound[it.title] and resIt.action == 'episodios':
|
||||
getattr(module, serversFound[it.title][0].action)(serversFound[it.title][0])
|
||||
else:
|
||||
serversFound[it.title] = [resIt]
|
||||
|
||||
if serversFound[it.title]:
|
||||
if hasattr(module, 'play'):
|
||||
tmp = []
|
||||
for srv in serversFound[it.title]:
|
||||
itPlay = getattr(module, 'play')(srv)
|
||||
if itPlay:
|
||||
tmp.append(itPlay[0])
|
||||
serversFound[it.title] = tmp
|
||||
for srv in serversFound[it.title]:
|
||||
itPlay = getattr(module, 'play')(srv)
|
||||
if itPlay:
|
||||
tmp.append(itPlay[0])
|
||||
serversFound[it.title] = tmp
|
||||
for srv in serversFound[it.title]:
|
||||
if srv.server:
|
||||
srv.foundOn = ch + ' --> ' + it.title + ' --> ' + resIt.title
|
||||
servers.append({'name': srv.server.lower(), 'server': srv})
|
||||
break
|
||||
except:
|
||||
if srv.server:
|
||||
srv.foundOn = ch + ' --> ' + it.title + ' --> ' + resIt.title
|
||||
servers.append({'name': srv.server.lower(), 'server': srv})
|
||||
break
|
||||
menuItemlist[it.title] = itemlist
|
||||
except Exception as ex:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
menuItemlist[it.title] = {
|
||||
'traceback': traceback.format_exc(),
|
||||
'exception': ex
|
||||
}
|
||||
|
||||
logMenu[it.title] = logger.recordedLog
|
||||
logger.recordedLog = ''
|
||||
@@ -220,9 +228,9 @@ for chItem in channel_list:
|
||||
# 'menuItemlist': {k: [it.tojson() if type(it) == Item else it for it in menuItemlist[k]] for k in menuItemlist.keys()},
|
||||
# 'serversFound': {k: [it.tojson() if type(it) == Item else it for it in menuItemlist[k]] for k in menuItemlist.keys()},
|
||||
# 'module': str(module), 'logMenu': logMenu, 'error': error})
|
||||
channels.append(
|
||||
{'ch': ch, 'hasChannelConfig': hasChannelConfig, 'mainlist': mainlist, 'menuItemlist': menuItemlist,
|
||||
'serversFound': serversFound, 'module': module, 'logMenu': logMenu, 'error': error})
|
||||
channels.append({'ch': ch, 'hasChannelConfig': hasChannelConfig, 'mainlist': mainlist,
|
||||
'menuItemlist': menuItemlist, 'serversFound': serversFound, 'module': module,
|
||||
'logMenu': logMenu, 'error': error})
|
||||
|
||||
logger.record = False
|
||||
|
||||
@@ -276,6 +284,10 @@ class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
print('testing ' + self.ch + ' --> ' + self.title)
|
||||
|
||||
logger.info(self.log)
|
||||
# returned an error
|
||||
if type(self.itemlist) == dict and self.itemlist['exception']:
|
||||
logger.error(self.itemlist['traceback'])
|
||||
raise self.itemlist['exception']
|
||||
|
||||
self.assertTrue(self.module.host, 'channel ' + self.ch + ' has not a valid hostname')
|
||||
self.assertTrue(self.itemlist, 'channel ' + self.ch + ' -> ' + self.title + ' is empty')
|
||||
@@ -286,10 +298,11 @@ class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
for content in chNumRis[self.ch]:
|
||||
if content in self.title:
|
||||
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>' +
|
||||
'<br>'.join([html.escape(i.title) for i in self.itemlist if not i.nextPage]))
|
||||
if 'Search' not in self.title:
|
||||
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>' +
|
||||
'<br>'.join([html.escape(i.title) for i in self.itemlist if not i.nextPage]))
|
||||
break
|
||||
|
||||
for resIt in self.itemlist:
|
||||
@@ -319,7 +332,7 @@ 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
|
||||
httptools.default_headers['Referer'] = self.server.referer
|
||||
# httptools.default_headers['Referer'] = self.server.referer
|
||||
print('testing ' + page_url)
|
||||
print('Found on ' + self.server.foundOn)
|
||||
print()
|
||||
|
||||
Reference in New Issue
Block a user