KoD 1.7.4

- Nuove visualizzazioni Server\n- Fix Gestione Viste\n- Aggiunto Pluto TV\n- Fix e migliorie varie\n\n
This commit is contained in:
marco
2022-02-12 12:54:50 +01:00
parent fa99565e9f
commit 41e0823f62
86 changed files with 1660 additions and 3471 deletions

View File

@@ -74,16 +74,21 @@ def get_platform(full_version=False):
codename = {"10": "dharma", "11": "eden", "12": "frodo",
"13": "gotham", "14": "helix", "15": "isengard",
"16": "jarvis", "17": "krypton", "18": "leia",
"19": "matrix"}
code_db = {'10': 'MyVideos37.db', '11': 'MyVideos60.db', '12': 'MyVideos75.db',
"19": "matrix", '20': 'nexus'}
video_db = {'10': 'MyVideos37.db', '11': 'MyVideos60.db', '12': 'MyVideos75.db',
'13': 'MyVideos78.db', '14': 'MyVideos90.db', '15': 'MyVideos93.db',
'16': 'MyVideos99.db', '17': 'MyVideos107.db', '18': 'MyVideos116.db',
'19': 'MyVideos119.db'}
'19': 'MyVideos119.db', '20': 'MyVideos120.db'}
view_db = {'10': 'ViewModes1.db', '11': 'ViewModes4.db', '12': 'ViewModes4.db',
'13': 'ViewModes6.db', '14': 'ViewModes6.db', '15': 'ViewModes6.db',
'16': 'ViewModes6.db', '17': 'ViewModes6.db', '18': 'ViewModes6.db',
'19': 'ViewModes6.db', '20': 'ViewModes6.db'}
num_version = xbmc.getInfoLabel('System.BuildVersion')
num_version = re.match("\d+\.\d+", num_version).group(0)
ret['name_version'] = codename.get(num_version.split('.')[0], num_version)
ret['video_db'] = code_db.get(num_version.split('.')[0], "")
ret['video_db'] = video_db.get(num_version.split('.')[0], "")
ret['view_db'] = view_db.get(num_version.split('.')[0], "")
ret['num_version'] = float(num_version)
if ret['num_version'] < 14:
ret['platform'] = "xbmc-" + ret['name_version']
@@ -443,3 +448,9 @@ def get_online_server_thumb(server):
def get_language():
return get_localized_string(20001)
def get_skin():
import xbmc
from core import jsontools
js = '{"jsonrpc": "2.0", "method": "Settings.GetSettingValue", "params": {"setting": "lookandfeel.skin"}, "id": 1 }'
return jsontools.load(xbmc.executeJSONRPC(js)).get('result', {}).get('value')

View File

@@ -2,27 +2,20 @@
# ------------------------------------------------------------
# XBMC Launcher (xbmc / kodi)
# ------------------------------------------------------------
import datetime
import json
import sys, os
import requests
PY3 = False
if sys.version_info[0] >= 3:PY3 = True; unicode = str; unichr = chr; long = int
import sys
from core.item import Item
from core import filetools, jsontools
from platformcode import config, logger, platformtools, xbmc_videolibrary
from core import filetools
from platformcode import config, logger, platformtools
from platformcode.logger import WebErrorException
temp_search_file = config.get_temp_file('temp-search')
def start():
""" First function that is executed when entering the plugin.
'''
First function that is executed when entering the plugin.
Within this function all calls should go to
functions that we want to execute as soon as we open the plugin.
"""
'''
logger.debug()
if not config.dev_mode():
@@ -31,124 +24,65 @@ def start():
changelog = fileC.read()
if changelog.strip():
platformtools.dialog_ok('Kodi on Demand', 'Aggiornamenti applicati:\n' + changelog)
os.remove(config.changelogFile)
filetools.remove(config.changelogFile)
except:
pass
def run(item=None):
logger.debug()
# Extract item from sys.argv
if not item: item = makeItem()
if not item:
# Extract item from sys.argv
if sys.argv[2]:
sp = sys.argv[2].split('&')
url = sp[0]
item = Item().fromurl(url)
if len(sp) > 1:
for e in sp[1:]:
key, val = e.split('=')
item.__setattr__(key, val)
# If no item, this is mainlist
else:
item = Item(channel="channelselector", action="getmainlist", viewmode="movie")
if not config.get_setting('show_once'):
if not config.get_all_settings_addon():
logger.error('corrupted settings.xml!!')
settings_xml = os.path.join(config.get_data_path(), "settings.xml")
settings_bak = os.path.join(config.get_data_path(), "settings.bak")
if filetools.exists(settings_bak):
filetools.copy(settings_bak, settings_xml, True)
logger.info('restored settings.xml from backup')
else:
filetools.write(settings_xml, '<settings version="2">\n</settings>') # resetted settings
else:
from platformcode import xbmc_videolibrary
xbmc_videolibrary.ask_set_content(silent=False)
config.set_setting('show_once', True)
# Load or Repare Settings
if not config.get_setting('show_once'): showOnce()
logger.info(item.tostring())
reload = False
from core import db
if db['OnPlay'].get('addon', False):
reload = True
db['OnPlay']['addon'] = False
db.close()
# Acrions
logger.debug(item.tostring())
try:
# Active tmdb
if not config.get_setting('tmdb_active'):
config.set_setting('tmdb_active', True)
# If item has no action, stops here
if item.action == "":
logger.debug("Item without action")
if item.action == '':
logger.debug('Item without action')
return
# Action for main menu in channelselector
elif item.action == "getmainlist":
# Channel Selector
if item.channel == 'channelselector':
itemlist = []
import channelselector
itemlist = channelselector.getmainlist()
if item.action == 'getmainlist': # Action for main menu in channelselector
itemlist = channelselector.getmainlist()
elif item.action == 'getchanneltypes': # Action for channel types on channelselector: movies, series, etc.
itemlist = channelselector.getchanneltypes()
elif item.action == 'filterchannels': # Action for channel listing on channelselector
itemlist = channelselector.filterchannels(item.channel_type)
platformtools.render_items(itemlist, item)
# Action for channel types on channelselector: movies, series, etc.
elif item.action == "getchanneltypes":
import channelselector
itemlist = channelselector.getchanneltypes()
platformtools.render_items(itemlist, item)
# Action for channel listing on channelselector
elif item.action == "filterchannels":
import channelselector
itemlist = channelselector.filterchannels(item.channel_type)
platformtools.render_items(itemlist, item)
# Special action for playing a video from the library
elif item.action == "play_from_library":
play_from_library(item)
return
elif item.action == 'play_from_library':
return playFromLibrary(item)
elif item.action == "keymap":
from platformcode import keymaptools
if item.open:
return keymaptools.open_shortcut_menu()
else:
return keymaptools.set_key()
# Special play action
elif item.action == 'play': play(item)
elif item.channel == "infoplus":
from platformcode import infoplus
return infoplus.Main(item)
# Special findvideos Action
elif item.action == 'findvideos': findvideos(item)
elif item.channel == "backup":
from platformcode import backup
return getattr(backup, item.action)(item)
# Special action for searching, first asks for the words then call the "search" function
elif item.action == 'search': search(item)
elif item.channel == "elementum_download":
from platformcode import elementum_download
return getattr(elementum_download, item.action)(item)
######## Following shares must be improved ########
elif item.channel == "shortcuts":
from platformcode import shortcuts
return getattr(shortcuts, item.action)(item)
elif item.channel == "autorenumber":
from platformcode import autorenumber
return getattr(autorenumber, item.action)(item)
elif item.action == "delete_key":
from platformcode import keymaptools
return keymaptools.delete_key()
elif item.action == "script":
from core import tmdb
tmdb.clean_cache()
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False)
# Special itemInfo Action
elif item.action == "itemInfo":
platformtools.dialog_textviewer('Item info', item.parent)
# Special action for open item.url in browser
elif item.action == "open_browser":
import webbrowser
if not webbrowser.open(item.url):
@@ -157,6 +91,8 @@ def run(item=None):
xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % item.url)
else:
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % "\n".join([item.url[j:j+57] for j in range(0, len(item.url), 57)]))
# Special gotopage Action
elif item.action == "gotopage":
page = platformtools.dialog_numeric(0, config.get_localized_string(70513))
if page:
@@ -169,163 +105,52 @@ def run(item=None):
item.url = re.sub('([=/])[0-9]+(/?)$', '\g<1>' + page + '\g<2>', item.url)
xbmc.executebuiltin("Container.Update(%s?%s)" % (sys.argv[0], item.tourl()))
elif reload and item.channel == 'filmontv' and item.action == 'new_search':
platformtools.fakeVideo()
import xbmc
return xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")")
else:
# Checks if channel exists
if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")):
CHANNELS = 'channels'
# Special action for adding a movie to the library
elif item.action == "add_pelicula_to_library":
from core import videolibrarytools
videolibrarytools.add_movie(item)
# Special action for adding a serie to the library
elif item.action == "add_serie_to_library":
channel = importChannel(item)
from core import videolibrarytools
videolibrarytools.add_tvshow(item, channel)
# Special action for adding a undefined to the library
elif item.action == "add_to_library":
channel = importChannel(item)
from core import videolibrarytools
videolibrarytools.add_to_videolibrary(item, channel)
# Special action for downloading all episodes from a serie
elif item.action == "download_all_episodes":
from specials import downloads
item.action = item.extra
del item.extra
downloads.save_download(item)
# keymaptools special actions
elif item.action == "keymap":
from platformcode import keymaptools
if item.open:
return keymaptools.open_shortcut_menu()
else:
CHANNELS = 'specials'
return keymaptools.set_key()
elif item.action == "delete_key":
from platformcode import keymaptools
return keymaptools.delete_key()
channel_file = os.path.join(config.get_runtime_path(), CHANNELS, item.channel + ".py")
# delete tmdb cache
elif item.action == "script":
from core import tmdb
tmdb.clean_cache()
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False)
logger.debug("channel_file= " + channel_file + ' - ' + CHANNELS + ' - ' + item.channel)
################################################
channel = None
# For all other actions
else: actions(item)
if os.path.exists(channel_file):
try:
channel = __import__('%s.%s' % (CHANNELS, item.channel), None, None, ['%s.%s' % (CHANNELS, item.channel)])
except ImportError:
exec("import " + CHANNELS + "." + item.channel + " as channel")
logger.info("Running channel %s | %s" % (channel.__name__, channel.__file__))
# Special play action
if item.action == "play":
# define la info para trakt
try:
from core import trakt_tools
trakt_tools.set_trakt_info(item)
except:
pass
logger.debug("item.action=%s" % item.action.upper())
# logger.debug("item_toPlay: " + "\n" + item.tostring('\n'))
# First checks if channel has a "play" function
if hasattr(channel, 'play'):
logger.debug("Executing channel 'play' method")
itemlist = channel.play(item)
b_favourite = item.isFavourite
# Play should return a list of playable URLS
if len(itemlist) > 0 and isinstance(itemlist[0], Item):
item = itemlist[0]
if b_favourite:
item.isFavourite = True
platformtools.play_video(item)
# Permitir varias calidades desde play en el Channel
elif len(itemlist) > 0 and isinstance(itemlist[0], list):
item.video_urls = itemlist
platformtools.play_video(item)
# If not, shows user an error message
else:
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339))
# If player don't have a "play" function, not uses the standard play from platformtools
else:
logger.debug("Executing core 'play' method")
platformtools.play_video(item)
# Special action for findvideos, where the plugin looks for known urls
elif item.action == "findvideos":
from core import servertools
if reload:
item.autoplay = True
platformtools.fakeVideo()
# First checks if channel has a "findvideos" function
if hasattr(channel, 'findvideos'):
itemlist = getattr(channel, item.action)(item)
# If not, uses the generic findvideos function
else:
logger.debug("No channel 'findvideos' method, " "executing core method")
itemlist = servertools.find_video_items(item)
if config.get_setting("max_links", "videolibrary") != 0:
itemlist = limit_itemlist(itemlist)
platformtools.render_items(itemlist, item)
# Special action for adding a movie to the library
elif item.action == "add_pelicula_to_library":
from core import videolibrarytools
videolibrarytools.add_movie(item)
# Special action for adding a serie to the library
elif item.action == "add_serie_to_library":
from core import videolibrarytools
videolibrarytools.add_tvshow(item, channel)
# Special action for adding a undefined to the library
elif item.action == "add_to_library":
from core import videolibrarytools
videolibrarytools.add_to_videolibrary(item, channel)
# Special action for downloading all episodes from a serie
elif item.action == "download_all_episodes":
from specials import downloads
item.action = item.extra
del item.extra
downloads.save_download(item)
# Special action for searching, first asks for the words then call the "search" function
elif item.action == "search":
if filetools.isfile(temp_search_file) and config.get_setting('videolibrary_kodi'):
itemlist = []
f = filetools.read(temp_search_file)
strList = f.split(',')
if strList[0] == '[V]' and strList[1] == item.channel:
for it in strList:
if it and it not in ['[V]', item.channel]:
itemlist.append(Item().fromurl(it))
filetools.write(temp_search_file, f[4:])
return platformtools.render_items(itemlist, item)
else:
filetools.remove(temp_search_file)
logger.debug("item.action=%s" % item.action.upper())
from core import channeltools
if config.get_setting('last_search'):
last_search = channeltools.get_channel_setting('Last_searched', 'search', '')
else:
last_search = ''
search_text = platformtools.dialog_input(last_search)
if search_text is not None:
channeltools.set_channel_setting('Last_searched', search_text, 'search')
itemlist = new_search(item.clone(text=search_text), channel)
else:
return
platformtools.render_items(itemlist, item)
# For all other actions
else:
logger.debug("Executing channel '%s' method" % item.action)
itemlist = getattr(channel, item.action)(item)
if config.get_setting('trakt_sync'):
from core import trakt_tools
token_auth = config.get_setting("token_trakt", "trakt")
if not token_auth:
trakt_tools.auth_trakt()
else:
import xbmc
if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting('install_trakt'):
trakt_tools.ask_install_script()
itemlist = trakt_tools.trakt_check(itemlist)
else:
config.set_setting('install_trakt', True)
platformtools.render_items(itemlist, item)
except WebErrorException as e:
@@ -337,24 +162,25 @@ def run(item=None):
platformtools.dialog_ok(
config.get_localized_string(59985) % e.channel,
config.get_localized_string(60013) % e.url)
except Exception as e:
import traceback
from core import scrapertools
logger.error(traceback.format_exc())
patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + r'([^.]+)\.py"'
patron = r'File "{}([^.]+)\.py"'.format(filetools.join(config.get_runtime_path(), 'channels', '').replace('\\', '\\\\'))
Channel = scrapertools.find_single_match(traceback.format_exc(), patron)
if Channel or e.__class__ == logger.ChannelScraperException:
if item.url:
if platformtools.dialog_yesno(config.get_localized_string(60087) % Channel, config.get_localized_string(60014), nolabel='ok', yeslabel=config.get_localized_string(70739)):
run(Item(action="open_browser", url=item.url))
run(Item(action='open_browser', url=item.url))
else:
platformtools.dialog_ok(config.get_localized_string(60087) % Channel, config.get_localized_string(60014))
else:
if platformtools.dialog_yesno(config.get_localized_string(60038), config.get_localized_string(60015)):
platformtools.itemlist_update(Item(channel="setting", action="report_menu"), True)
platformtools.itemlist_update(Item(channel='setting', action='report_menu'), True)
finally:
# db need to be closed when not used, it will cause freezes
from core import db
@@ -374,196 +200,195 @@ def new_search(item, channel=None):
writelist = item.channel
for it in itemlist:
writelist += ',' + it.tourl()
filetools.write(temp_search_file, writelist)
# filetools.write(temp_search_file, writelist)
return itemlist
def set_search_temp(item):
if filetools.isfile(temp_search_file) and config.get_setting('videolibrary_kodi'):
f = '[V],' + filetools.read(temp_search_file)
filetools.write(temp_search_file, f)
def reorder_itemlist(itemlist):
def limitItemlist(itemlist):
logger.debug()
# logger.debug("Inlet itemlist size: %i" % len(itemlist))
new_list = []
mod_list = []
not_mod_list = []
modified = 0
not_modified = 0
to_change = [[config.get_localized_string(60335), '[V]'], [config.get_localized_string(60336), '[D]']]
for item in itemlist:
if not PY3:
old_title = unicode(item.title, "utf8").lower().encode("utf8")
else:
old_title = item.title.lower()
for before, after in to_change:
if before in item.title:
item.title = item.title.replace(before, after)
break
if not PY3:
new_title = unicode(item.title, "utf8").lower().encode("utf8")
else:
new_title = item.title.lower()
if old_title != new_title:
mod_list.append(item)
modified += 1
else:
not_mod_list.append(item)
not_modified += 1
# logger.debug("OLD: %s | NEW: %s" % (old_title, new_title))
new_list.extend(mod_list)
new_list.extend(not_mod_list)
logger.debug("Modified Titles:%i |Unmodified:%i" % (modified, not_modified))
if len(new_list) == 0:
new_list = itemlist
# logger.debug("Outlet itemlist size: %i" % len(new_list))
return new_list
def limit_itemlist(itemlist):
logger.debug()
# logger.debug("Inlet itemlist size: %i" % len(itemlist))
try:
opt = config.get_setting("max_links", "videolibrary")
if opt == 0:
value = config.get_setting('max_links', 'videolibrary')
if value == 0:
new_list = itemlist
else:
i_max = 30 * opt
new_list = itemlist[:i_max]
# logger.debug("Outlet itemlist size: %i" % len(new_list))
new_list = itemlist[:value]
return new_list
except:
return itemlist
def play_from_library(item):
"""
The .strm files when played from kodi, this expects it to be a "playable" file so it cannot contain
more items, at most a selection dialog can be placed.
We solve this by "cheating kodi" and making him believe that something has been reproduced, so later by
"Container.Update ()" we load the strm as if an item from inside the addon were treated, removing all
the limitations and allowing to reproduce through the general function without having to create new methods to
the video library.
@type item: item
@param item: item with information
"""
def get_played_time(item):
from core import videolibrarytools
if item.contentType == 'movie':
nfo_path = item.nfo
if nfo_path.startswith('\\') or nfo_path.startswith('/'):
nfo_path = filetools.join(videolibrarytools.MOVIES_PATH, nfo_path)
else:
nfo_path =item.strm_path.replace('strm','nfo')
if nfo_path.startswith('\\') or nfo_path.startswith('/'):
nfo_path = filetools.join(videolibrarytools.TVSHOWS_PATH, nfo_path)
if nfo_path and filetools.isfile(nfo_path):
head_nfo, item_nfo = videolibrarytools.read_nfo(nfo_path)
sleep(1)
played_time = platformtools.get_played_time(item_nfo)
else: played_time = 0
return played_time
import xbmcgui, xbmcplugin, xbmc
from time import sleep
if not item.autoplay and not item.next_ep:
platformtools.fakeVideo()
itemlist=[]
item.fromLibrary = True
item.window = True
def makeItem():
logger.debug()
# Modify the action (currently the video library needs "findvideos" since this is where the sources are searched
item.action = item.next_action if item.next_action else "findvideos"
if item.contentType == 'movie' or item.contentType != 'movie' and config.get_setting('next_ep') < 3:
window_type = config.get_setting("window_type", "videolibrary")
else: window_type = 1
# and launch kodi again
if (xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1) or item.action != 'findvideos':
xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")")
if sys.argv[2]:
sp = sys.argv[2].split('&')
url = sp[0]
item = Item().fromurl(url)
if len(sp) > 1:
for e in sp[1:]:
key, val = e.split('=')
if val.lower() == 'false': val = False
elif val.lower() == 'true': val = True
item.__setattr__(key, val)
# If no item, this is mainlist
else:
# Pop-up window
from specials import videolibrary
from core.channeltools import get_channel_parameters
item = Item(channel='channelselector', action='getmainlist', viewmode='movie')
return item
def showOnce():
if not config.get_all_settings_addon():
logger.error('corrupted settings.xml!!')
settings_xml = filetools.join(config.get_data_path(), 'settings.xml')
settings_bak = filetools.join(config.get_data_path(), 'settings.bak')
if filetools.exists(settings_bak):
filetools.copy(settings_bak, settings_xml, True)
logger.info('restored settings.xml from backup')
else:
filetools.write(settings_xml, '<settings version="2">\n</settings>') # resetted settings
else:
from platformcode import xbmc_videolibrary
xbmc_videolibrary.ask_set_content(silent=False)
config.set_setting('show_once', True)
def play(item):
channel = importChannel(item)
# define info for trakt
try:
from core import trakt_tools
trakt_tools.set_trakt_info(item)
except:
pass
logger.debug('item.action=', item.action.upper())
# First checks if channel has a "play" function
if hasattr(channel, 'play'):
logger.debug('Executing channel "play" method')
itemlist = channel.play(item)
# Play should return a list of playable URLS
if len(itemlist) > 0 and isinstance(itemlist[0], Item):
item = itemlist[0]
platformtools.play_video(item)
# Allow several qualities from Play in El Channel
elif len(itemlist) > 0 and isinstance(itemlist[0], list):
item.video_urls = itemlist
platformtools.play_video(item)
# If not, shows user an error message
else:
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339))
# If player don't have a "play" function, not uses the standard play from platformtools
else:
logger.debug('Executing core "play" method')
platformtools.play_video(item)
def findvideos(item, itemlist=[]):
if not itemlist:
logger.debug('Executing channel', item.channel, 'method', item.action)
channel = importChannel(item)
from core import servertools
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
p_dialog.update(0, '')
item.play_from = 'window'
itemlist = videolibrary.findvideos(item)
p_dialog.update(100, ''); sleep(0.5); p_dialog.close()
played = False
p_dialog.update(0)
# The number of links to show is limited
if config.get_setting("max_links", "videolibrary") != 0: itemlist = limit_itemlist(itemlist)
# The list of links is slightly "cleaned"
if config.get_setting("replace_VD", "videolibrary") == 1: itemlist = reorder_itemlist(itemlist)
try:
# First checks if channel has a "findvideos" function
if hasattr(channel, 'findvideos'):
itemlist = getattr(channel, item.action)(item)
if len(itemlist) > 0:
reopen = False
# If not, uses the generic findvideos function
else:
logger.debug('No channel "findvideos" method, executing core method')
itemlist = servertools.find_video_items(item)
while not xbmc.Monitor().abortRequested():
played = True
# if config.get_setting('next_ep') == 3 and xbmc.Player().playnext:
# return
# The user chooses the mirror
if not platformtools.is_playing():
if config.get_setting('next_ep') == 3:
xbmc.sleep(500)
if platformtools.is_playing():
return
if config.get_setting('autoplay') or reopen:
played_time = get_played_time(item)
if not played_time and played:
return
itemlist = limitItemlist(itemlist)
except Exception as ex:
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error(" %s" % message)
options = []
selection_implementation = 0
for item in itemlist:
item.thumbnail = config.get_online_server_thumb(item.server)
quality = '[B][' + item.quality + '][/B]' if item.quality else ''
if item.server:
path = filetools.join(config.get_runtime_path(), 'servers', item.server.lower() + '.json')
name = jsontools.load(open(path, "rb").read())['name']
if name.startswith('@'): name = config.get_localized_string(int(name.replace('@','')))
logger.debug(item)
it = xbmcgui.ListItem('\n[B]%s[/B] %s - %s [%s]' % (name, quality, item.contentTitle, get_channel_parameters(item.contentChannel)['title']))
it.setArt({'thumb':item.thumbnail})
options.append(it)
else:
selection_implementation += 1
# The selection window opens
if (item.contentSerieName and item.contentSeason and item.contentEpisodeNumber): head = ("%s - %sx%s | %s" % (item.contentSerieName, item.contentSeason, item.contentEpisodeNumber, config.get_localized_string(30163)))
else: head = config.get_localized_string(30163)
selection = platformtools.dialog_select(head, options, preselect= -1, useDetails=True)
if selection == -1:
return
else:
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
p_dialog.update(100)
p_dialog.close()
serverlist = [s for s in itemlist if s.server]
if itemlist and not serverlist:
platformtools.render_items(itemlist, item)
if not serverlist:
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60347))
elif len(serverlist) == 1:
# If there is only one server play it immediately
play(itemlist[0].clone(no_return=True))
else:
platformtools.serverWindow(item, itemlist)
def search(item):
channel = importChannel(item)
from core import channeltools
if config.get_setting('last_search'):
last_search = channeltools.get_channel_setting('Last_searched', 'search', '')
else:
last_search = ''
search_text = platformtools.dialog_input(last_search)
if search_text is not None:
channeltools.set_channel_setting('Last_searched', search_text, 'search')
itemlist = new_search(item.clone(text=search_text), channel)
else:
return
platformtools.render_items(itemlist, item)
def addToLibrary(item):
channel = importChannel(item)
from core import videolibrarytools
videolibrarytools.add_to_videolibrary(item, channel)
def importChannel(item):
channel = platformtools.channelImport(item.channel)
if not channel:
logger.debug('Channel', item.channel, 'not exist!')
return
logger.debug('Running channel', channel.__name__, '|', channel.__file__)
return channel
def actions(item):
logger.debug('Executing channel', item.channel, 'method', item.action)
channel = importChannel(item)
itemlist = getattr(channel, item.action)(item)
if type(itemlist) == list:
if config.get_setting('trakt_sync'):
from core import trakt_tools
token_auth = config.get_setting('token_trakt', 'trakt')
if not token_auth:
trakt_tools.auth_trakt()
else:
import xbmc
if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting('install_trakt'):
trakt_tools.ask_install_script()
itemlist = trakt_tools.trakt_check(itemlist)
else:
config.set_setting('install_trakt', True)
if item.action in ['check'] and len([s for s in itemlist if s.server]) > 0:
findvideos(item, itemlist)
else:
platformtools.render_items(itemlist, item)
def playFromLibrary(item):
if not item.next_ep: platformtools.fakeVideo()
item.action = item.next_action if item.next_action else 'findvideos'
logger.debug('Executing channel', item.channel, 'method', item.action)
return run(item)

View File

@@ -10,9 +10,12 @@ import sys
if sys.version_info[0] >= 3:
PY3 = True
import urllib.parse as urllib
from concurrent import futures
else:
PY3 = False
import urllib
from concurrent_py2 import futures
import os, xbmc, xbmcgui, xbmcplugin
from past.utils import old_div
@@ -310,47 +313,70 @@ def render_items(itemlist, parent_item):
"""
Function used to render itemlist on kodi
"""
# if it's not a list, do nothing
if not isinstance(itemlist, list):
return
logger.debug('START render_items')
logger.debug('START renderItems')
thumb_type = config.get_setting('video_thumbnail_type')
from platformcode import shortcuts
# from core import httptools
_handle = int(sys.argv[1])
default_fanart = config.get_fanart()
def_context_commands = shortcuts.context()
# if there's no item, add "no elements" item
if not len(itemlist):
itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png')))
from core.support import thumb
itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=thumb('nofolder')))
mode, Type = get_view_mode(itemlist[0], parent_item)
# from core.support import dbg;dbg()
if mode:
set_view_mode(sys.argv[2], mode)
dirItems = []
for n, item in enumerate(itemlist):
# item.itemlistPosition = n + 1
def setItem(n, item, parent_item):
item.itemlistPosition = n
item_url = item.tourl()
if item.category == "":
item.category = parent_item.category
if not item.title:
item.title = ''
# If there is no action or it is findvideos / play, folder = False because no listing will be returned
if item.action in ['play', '']:
if item.action in ['play', 'findvideos', '']:
item.folder = False
if item.fanart == "":
item.fanart = parent_item.fanart
if item.action == 'play' and thumb_type == 1 and not item.forcethumb:
item.thumbnail = config.get_online_server_thumb(item.server)
icon_image = "DefaultFolder.png" if item.folder else "DefaultVideo.png"
listitem = xbmcgui.ListItem(item.title)
listitem.setArt({'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail,
'fanart': item.fanart if item.fanart else default_fanart})
title = item.title
listitem = xbmcgui.ListItem(title)
art = {'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail, 'fanart': item.fanart if item.fanart else default_fanart}
if item.infoLabels.get('landscape'): art['landscape'] = item.infoLabels['landscape']
if item.infoLabels.get('clearlogo'): art['clearlogo'] = item.infoLabels['clearlogo']
if item.infoLabels.get('clearart'): art['clearart'] = item.infoLabels['clearart']
if item.infoLabels.get('banner'): art['banner'] = item.infoLabels['banner']
if item.infoLabels.get('disc'): art['disc'] = item.infoLabels['disc']
listitem.setProperty('ResumeTime', str(get_played_time(item)))
listitem.setArt(art)
if config.get_setting("player_mode") == 1 and item.action == "play" and not item.nfo:
listitem.setProperty('IsPlayable', 'true')
if item.infoLabels.get('castandrole'):
try:
cast = [{'name':c[0], 'role':c[1], 'thumbnail':c[2], 'order':c[3]} for c in item.infoLabels.get("castandrole", [])]
cast.sort(key=lambda c: c['order'])
listitem.setCast(cast)
del item.infoLabels['castandrole']
except:
pass
set_infolabels(listitem, item)
# context menu
@@ -359,12 +385,31 @@ def render_items(itemlist, parent_item):
else:
context_commands = def_context_commands
listitem.addContextMenuItems(context_commands)
return item, item_url, listitem
dirItems.append(('%s?%s' % (sys.argv[0], item_url), listitem, item.folder))
# For Debug
# from core.support import dbg;dbg()
# r_list = [setItem(i, item, parent_item) for i, item in enumerate(itemlist)]
set_view_mode(itemlist[0], parent_item)
r_list = []
with futures.ThreadPoolExecutor() as executor:
searchList = [executor.submit(setItem, i, item, parent_item) for i, item in enumerate(itemlist)]
for res in futures.as_completed(searchList):
r_list.append(res.result())
r_list.sort(key=lambda it: it[0].itemlistPosition)
for item, item_url, listitem in r_list:
dirItems.append(('{}?{}'.format(sys.argv[0], item_url), listitem, item.folder, len(r_list)))
xbmcplugin.addDirectoryItems(_handle, dirItems)
if Type: xbmcplugin.setContent(handle=int(sys.argv[1]), content=Type)
if parent_item.sorted:
if parent_item.sorted == 'year': xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
elif parent_item.sorted == 'name':xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE)
if parent_item.list_type == '':
breadcrumb = parent_item.category #.capitalize()
else:
@@ -378,40 +423,41 @@ def render_items(itemlist, parent_item):
xbmcplugin.setPluginCategory(handle=_handle, category=breadcrumb)
xbmcplugin.endOfDirectory(_handle, succeeded=True, updateListing=False, cacheToDisc= True) # if parent_item.action in ['news', 'search', 'new_search', 'now_on_tv'] else False)
# if mode:
# xbmc.sleep(50)
# xbmc.executebuiltin('Container.SetViewMode(%s)' % mode)
# cacheToDisc = False
# if (parent_item.action == 'findvideos' and config.get_setting('autoplay')) or parent_item.action == 'search':
# cacheToDisc = True
xbmcplugin.endOfDirectory(_handle, succeeded=True, updateListing=False, cacheToDisc=True)
logger.debug('END render_items')
from core import db; db.close()
logger.debug('END renderItems')
def viewmodeMonitor():
# logger.debug('WINDOW:',get_window())
# logger.debug('WINDOW:',get_window(), xbmcgui.getCurrentWindowId())
if get_window() == 'WINDOW_VIDEO_NAV':
try:
currentModeName = xbmc.getInfoLabel('Container.Viewmode')
parent_info = xbmc.getInfoLabel('Container.FolderPath')
item_info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath')
win = xbmcgui.Window(10025)
currentMode = int(win.getFocusId())
# logger.debug('CM', currentMode, 'CN',currentModeName, 'label',xbmc.getInfoLabel('Container.FolderPath'))
# if not parent_info:
if 'plugin.video.kod' in parent_info:
parent = Item().fromurl(parent_info, silent=True)
item = Item().fromurl(xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath'), silent=True)
currentModeName = xbmc.getInfoLabel('Container.Viewmode')
currentMode = int(xbmcgui.Window(10025).getFocusId())
# logger.debug('SAVE VIEW 1', currentMode, parent.action, item.action)
if 50 <= currentMode < 520 and parent and parent.action != item.action:
content, Type = getCurrentView(item, parent)
view_mode_type = config.get_setting('view_mode_%s' % content)
# logger.debug('VIEW MODE TYPE')
if view_mode_type:
defaultMode = int(view_mode_type.split(',')[-1])
if content and currentMode != defaultMode:
config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode))
# logger.debug('SAVE VIEW 2', defaultMode, '->', currentMode)
if config.get_setting('viewchange_notify'):
dialog_notification(config.get_localized_string(70153),
config.get_localized_string(70187) % (content, currentModeName),
sound=False)
if currentModeName and 'plugin.video.kod' in parent_info and 50 <= currentMode < 1000:# and currentMode >= 50: # inside addon and in itemlist view
# logger.debug('CAMBIO VISUALE')
content, Type = getCurrentView(Item().fromurl(item_info) if item_info else Item(), Item().fromurl(parent_info))
if content:
defaultMode = int(config.get_setting('view_mode_%s' % content).split(',')[-1])
if currentMode != defaultMode:
# logger.debug('viewmode changed: ' + currentModeName + '-' + str(currentMode) + ' - content: ' + content)
config.set_setting('view_mode_%s' % content, currentModeName + ', ' + str(currentMode))
if config.get_setting('viewchange_notify'):
dialog_notification(config.get_localized_string(70153),
config.get_localized_string(70187) % (content, currentModeName),
sound=False)
except:
import traceback
logger.error(traceback.print_exc())
@@ -422,20 +468,9 @@ def getCurrentView(item=None, parent_item=None):
if not item:
item = Item()
if not parent_item:
logger.debug('ESCO')
# logger.debug('ESCO')
return None, None
# if not parent_item:
# info = xbmc.getInfoLabel('Container.FolderPath')
# if not info:
# return None, None
# parent_item = Item().fromurl(info)
# if not item:
# info = xbmc.getInfoLabel('Container.ListItemPosition(2).FileNameAndPath') # first addon listitem (consider "..")
# if not info:
# item = Item()
# else:
# item = Item().fromurl(info) if info else Item()
parent_actions = ['peliculas', 'novedades', 'search', 'get_from_temp', 'newest', 'discover_list', 'new_search', 'channel_search']
addons = 'addons' if config.get_setting('touch_view') else ''
@@ -446,6 +481,9 @@ def getCurrentView(item=None, parent_item=None):
elif parent_item.action == 'mainlist':
return 'channel', addons
elif item.contentType == 'music':
return 'musicvideo', 'musicvideos'
elif (item.contentType in ['movie'] and parent_item.action in parent_actions) \
or (item.channel in ['videolibrary'] and parent_item.action in ['list_movies']) \
or (parent_item.channel in ['favorites'] and parent_item.action in ['mainlist']) \
@@ -460,11 +498,10 @@ def getCurrentView(item=None, parent_item=None):
return 'episode', 'tvshows'
elif parent_item.action in ['get_seasons']:
logger.debug('CONTENTTYPE:',item.contentType)
return 'season', 'tvshows'
elif parent_item.action in ['getmainlist', '', 'getchanneltypes']:
return 'home', addons
return None, None
elif parent_item.action in ['filterchannels']:
return 'channels', addons
@@ -476,27 +513,84 @@ def getCurrentView(item=None, parent_item=None):
return None, None
def set_view_mode(item, parent_item):
def get_view_mode(item, parent_item):
def reset_view_mode():
for mode in ['home','menu','channels','channel','movie','tvshow','season','episode','server']:
config.set_setting('skin_name', xbmc.getSkinDir())
config.set_setting('view_mode_%s' % mode, config.get_localized_string(70003) + ' , 0')
content, Type = getCurrentView(item, parent_item)
if xbmc.getSkinDir() != config.get_setting('skin_name') or not config.get_setting('skin_name'):
reset_view_mode()
xbmcplugin.setContent(handle=int(sys.argv[1]), content='')
xbmc.executebuiltin('Container.SetViewMode(%s)' % 55)
return 55, Type
content, Type = getCurrentView(item, parent_item)
if content:
mode = int(config.get_setting('view_mode_%s' % content).split(',')[-1])
if mode == 0:
logger.debug('default mode')
mode = 55
xbmcplugin.setContent(handle=int(sys.argv[1]), content=Type)
xbmc.executebuiltin('Container.SetViewMode(%s)' % mode)
logger.debug('TYPE: ' + Type + ' - ' + 'CONTENT: ' + content)
return mode, Type
return None, None
def set_view_mode(url, mode):
import re
find = re.findall('(%\d\w)', url, flags=re.DOTALL)
for f in find:
url = url.replace(f, f.lower())
def get_connection():
from core import filetools
file_db = ""
# We look for the archive of the video database according to the version of kodi
view_db = config.get_platform(True)['view_db']
if view_db:
file_db = filetools.join(xbmc.translatePath("special://userdata/Database"), view_db)
# alternative method to locate the database
if not file_db or not filetools.exists(file_db):
file_db = ""
for f in filetools.listdir(xbmc.translatePath("special://userdata/Database")):
path_f = filetools.join(xbmc.translatePath("special://userdata/Database"), f)
if filetools.isfile(path_f) and f.lower().startswith('viewmodes') and f.lower().endswith('.db'):
file_db = path_f
break
try:
import sqlite3
return sqlite3.connect(file_db)
except:
return None
def execute_sql(conn, sql):
cursor = conn.cursor()
cursor.execute(sql)
conn.commit()
return cursor.fetchall()
conn = get_connection()
if conn:
skin_name = config.get_skin()
try:
sql = 'select idView from view where (path="{}{}" and skin="{}")'.format(sys.argv[0], url, skin_name)
records = execute_sql(conn, sql)
if records:
# from core.support import dbg;dbg()
sql = 'update view set viewMode={} where idView={}'.format(mode, records[0][0])
records = execute_sql(conn, sql)
else:
# from core.support import dbg;dbg()
sql = 'INSERT INTO view (window, path, viewMode, sortMethod, sortOrder, sortAttributes, skin) VALUES ' \
'(10025, "{}{}", {}, 0, 1, 0, "{}")'.format(sys.argv[0], url, mode, skin_name)
records = execute_sql(conn, sql)
except:
pass
conn.close()
def set_infolabels(listitem, item, player=False):
@@ -511,33 +605,23 @@ def set_infolabels(listitem, item, player=False):
@type item: item
"""
infoLabels_dict = {'aired': 'aired', 'album': 'album', 'artist': 'artist', 'cast': 'cast',
'castandrole': 'castandrole', 'tmdb_id': 'code', 'code': 'code', 'country': 'country',
'credits': 'credits', 'release_date': 'dateadded', 'dateadded': 'dateadded', 'dbid': 'dbid',
'director': 'director', 'duration': 'duration', 'episode': 'episode',
'episodio_sinopsis': 'episodeguide', 'episodio_air_date': 'None', 'episodio_imagen': 'None',
'episodio_titulo': 'title', 'episodio_vote_average': 'rating', 'episodio_vote_count': 'votes',
'fanart': 'None', 'genre': 'genre', 'homepage': 'None', 'imdb_id': 'imdbnumber',
'imdbnumber': 'imdbnumber', 'in_production': 'None', 'last_air_date': 'lastplayed',
'mediatype': 'mediatype', 'mpaa': 'mpaa', 'number_of_episodes': 'None',
'number_of_seasons': 'None', 'original_language': 'None', 'originaltitle': 'originaltitle',
'overlay': 'overlay', 'poster_path': 'path', 'popularity': 'None', 'playcount': 'playcount',
'plot': 'plot', 'plotoutline': 'plotoutline', 'premiered': 'premiered', 'quality': 'None',
'rating': 'rating', 'season': 'season', 'set': 'set', 'setid': 'setid',
'setoverview': 'setoverview', 'showlink': 'showlink', 'sortepisode': 'sortepisode',
'sortseason': 'sortseason', 'sorttitle': 'sorttitle', 'status': 'status', 'studio': 'studio',
'tag': 'tag', 'tagline': 'tagline', 'temporada_air_date': 'None', 'temporada_nombre': 'None',
'temporada_num_episodios': 'None', 'temporada_poster': 'None', 'title': 'title',
'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'thumbnail': 'None',
'tvdb_id': 'None', 'tvshowtitle': 'tvshowtitle', 'type': 'None', 'userrating': 'userrating',
'url_scraper': 'None', 'votes': 'votes', 'writer': 'writer', 'year': 'year'}
infoLabels_dict = {'aired': 'aired', 'album': 'album', 'artist': 'artist', 'cast': 'cast', 'castandrole': 'castandrole',
'tmdb_id': 'code', 'code': 'code', 'country': 'country', 'credits': 'credits', 'release_date': 'dateadded',
'dateadded': 'dateadded', 'dbid': 'dbid', 'director': 'director', 'duration': 'duration', 'episode': 'episode',
'episode_plot': 'episodeguide', 'episode_title': 'title', 'episode_vote_average': 'rating', 'episode_vote_count': 'votes',
'genre': 'genre', 'imdb_id': 'imdbnumber', 'imdbnumber': 'imdbnumber', 'last_air_date': 'lastplayed', 'mediatype': 'mediatype',
'mpaa': 'mpaa', 'originaltitle': 'originaltitle', 'overlay': 'overlay', 'poster_path': 'path', 'playcount': 'playcount',
'plot': 'plot', 'plotoutline': 'plotoutline', 'premiered': 'premiered', 'rating': 'rating', 'season': 'season', 'set': 'set',
'setid': 'setid', 'setoverview': 'setoverview', 'showlink': 'showlink', 'sortepisode': 'sortepisode', 'sortseason': 'sortseason',
'sorttitle': 'sorttitle', 'status': 'status', 'studio': 'studio', 'tag': 'tag', 'tagline': 'tagline', 'title': 'title',
'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'tvshowtitle': 'tvshowtitle', 'userrating': 'userrating',
'votes': 'votes', 'writer': 'writer', 'year': 'year'}
# if item.infoLabels:
try:
infoLabels_kodi = {infoLabels_dict[label_tag]: item.infoLabels[label_tag] for label_tag, label_value in list(item.infoLabels.items()) if infoLabels_dict[label_tag] != 'None'}
infoLabels_kodi = {infoLabels_dict[label_tag]: label_value for label_tag, label_value in list(item.infoLabels.items()) if label_tag in infoLabels_dict}
listitem.setInfo("video", infoLabels_kodi)
except:
listitem.setInfo("video", item.infoLabels)
# logger.error(item.infoLabels)
def set_context_commands(item, item_url, parent_item, **kwargs):
@@ -605,39 +689,16 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
else:
context_commands.append((command["title"], "RunPlugin(%s?%s)" % (sys.argv[0], item.clone(**command).tourl())))
# Do not add more predefined options if you are inside kodfavoritos
# if parent_item.channel == 'kodfavorites':
# return context_commands
if parent_item.channel == 'kodfavorites':
if config.dev_mode():
context_commands.insert(0, ("item info", "Container.Update (%s?%s)" % (sys.argv[0], Item(action="itemInfo", parent=item.tojson()).tourl())))
return context_commands
# Options according to criteria, only if the item is not a tag, nor is it "Add to the video library", etc...
if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer", "actualizar_titulos"]:
# Show information: if the item has a plot, we assume that it is a series, season, chapter or movie
# if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'):
# context_commands.append((config.get_localized_string(60348), "Action(Info)"))
if item.channel != "videolibrary" and item.videolibrary != False and not item.disable_videolibrary:
# Add Series to the video library
if item.action in ["episodios", "get_episodios", "get_seasons"] and item.contentSerieName:
context_commands.append((config.get_localized_string(60352), "RunPlugin(%s?%s&%s)" % (
sys.argv[0], item_url, 'action=add_serie_to_library&from_action=' + item.action)))
# Add Movie to Video Library
elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle:
context_commands.append((config.get_localized_string(60353), "RunPlugin(%s?%s&%s)" % (
sys.argv[0], item_url, 'action=add_pelicula_to_library&from_action=' + item.action)))
# Add to Video Library
elif item.action in ['check'] and item.contentTitle:
context_commands.append((config.get_localized_string(30161), "RunPlugin(%s?%s&%s)" % (
sys.argv[0], item_url, 'action=add_to_library&from_action=' + item.action)))
# Search trailer...
if (item.contentTitle and item.contentType in ['movie', 'tvshow']) or "buscar_trailer" in context:
context_commands.append((config.get_localized_string(60359), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({ 'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.contentTitle if item.contentTitle else item.fulltitle, 'contextual': True}))))
# Add to kodfavoritos (My links)
if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "kodfavorites":
context_commands.append( (config.get_localized_string(70557), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "kodfavorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action}))))
# Add to kodfavoritos
if parent_item.channel == 'globalsearch':
context_commands.append( (config.get_localized_string(30155), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "favorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action}))))
# InfoPlus
if config.get_setting("infoplus"):
#if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \
@@ -645,8 +706,35 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']:
context_commands.append(("InfoPlus", "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'channel=infoplus&action=Main&from_channel=' + item.channel)))
# Search in other channels
if item.contentTitle and item.contentType in ['movie', 'tvshow'] and parent_item.channel not in ['search', 'globalsearch'] and item.action not in ['play']: #and parent_item.action != 'mainlist':
if item.channel != "videolibrary" and item.videolibrary != False and not item.disable_videolibrary:
# Add Series to the video library
if item.action in ["episodios", "get_episodios", "get_seasons"] and item.contentSerieName:
context_commands.append((config.get_localized_string(60352), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_serie_to_library&from_action=' + item.action)))
# Add Movie to Video Library
elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle:
context_commands.append((config.get_localized_string(60353), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_pelicula_to_library&from_action=' + item.action)))
# Add to Video Library
elif item.action in ['check'] and item.contentTitle:
context_commands.append((config.get_localized_string(30161), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, 'action=add_to_library&from_action=' + item.action)))
# Search trailer...
if (item.contentTitle and item.contentType in ['movie', 'tvshow']) or "buscar_trailer" in context:
context_commands.append((config.get_localized_string(60359), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({ 'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.contentTitle if item.contentTitle else item.fulltitle, 'contextual': True}))))
# Add to kodfavoritos (My links)
if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "favorites" and parent_item.from_channel != "kodfavorites":
context_commands.append( (config.get_localized_string(70557), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "kodfavorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action}))))
# Add to kodfavoritos
if parent_item.channel == 'globalsearch':
context_commands.append( (config.get_localized_string(30155), "RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': "favorites", 'action': "addFavourite", 'from_channel': item.channel, 'from_action': item.action}))))
# Open in browser and previous menu
if parent_item.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist":
context_commands.append((config.get_localized_string(70739), "Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl())))
# Search in other channels
if item.contentTitle and item.contentType in ['movie', 'tvshow'] and parent_item.channel not in ['search', 'globalsearch'] and item.action not in ['play'] and parent_item.action != 'mainlist':
# Search in other channels
if item.contentSerieName != '':
@@ -665,11 +753,6 @@ def set_context_commands(item, item_url, parent_item, **kwargs):
context_commands.append((config.get_localized_string(60350), "Container.Refresh (%s?%s&%s)" % (sys.argv[0], item_url, urllib.urlencode({'channel': 'search', 'action': "from_context", 'from_channel': item.channel, 'contextual': True, 'text': item.wanted}))))
context_commands.append( (config.get_localized_string(70561), "Container.Update (%s?%s&%s)" % (sys.argv[0], item_url, 'channel=search&action=from_context&search_type=list&page=1&list_type=%s/%s/similar' % (mediatype, item.infoLabels['tmdb_id']))))
# Open in browser and previous menu
if parent_item.channel not in ["news", "channelselector", "downloads", "search"] and item.action != "mainlist" and not parent_item.noMainMenu:
context_commands.append((config.get_localized_string(70739), "Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl())))
if not item.local and item.channel not in ["downloads", "filmontv", "search"] and item.server != 'torrent' and parent_item.action != 'mainlist' and config.get_setting('downloadenabled') and not item.disable_videolibrary:
# Download movie
if item.contentType == "movie":
@@ -960,6 +1043,7 @@ def get_window():
def play_video(item, strm=False, force_direct=False, autoplay=False):
from core import httptools
logger.debug()
logger.debug(item.tostring('\n'))
@@ -977,7 +1061,6 @@ def play_video(item, strm=False, force_direct=False, autoplay=False):
# pass referer
if item.referer:
from core import httptools
httptools.default_headers['Referer'] = item.referer
# Open the selection dialog to see the available options
@@ -999,9 +1082,33 @@ def play_video(item, strm=False, force_direct=False, autoplay=False):
# we get the selected video
mediaurl, view, mpd, hls = get_video_seleccionado(item, seleccion, video_urls, autoplay)
if not mediaurl: return
# to better disguise KoD as a browser
headers = {'User-Agent': httptools.get_user_agent(), 'Referer': item.referer if item.server == 'directo' else item.url}
# Kodi does not seems to allow this, leaving there as may work in the future
# if config.get_setting('resolver_dns'):
# try:
# import urllib.parse as urlparse
# except ImportError:
# import urlparse
# from lib import doh
# try:
# parse = urlparse.urlparse(mediaurl)
# if parse.netloc:
# domain = parse.netloc
# if not scrapertools.find_single_match(domain, '\d+\.\d+\.\d+\.\d+'):
# ip = doh.query(domain)[0]
# logger.info('Query DoH: ' + domain + ' = ' + str(ip))
# parse = list(parse)
# parse[1] = ip
# mediaurl = urlparse.urlunparse(parse)
# headers['Host'] = domain
# except:
# logger.error('Failed to resolve hostname, fallback to normal dns')
if '|' not in mediaurl:
mediaurl = mediaurl + '|' + urllib.urlencode(headers)
# video information is obtained.
xlistitem = xbmcgui.ListItem(path=item.url)
xlistitem = xbmcgui.ListItem(item.title, path=item.url)
xlistitem.setArt({"thumb": item.contentThumbnail if item.contentThumbnail else item.thumbnail})
set_infolabels(xlistitem, item, True)
@@ -1016,12 +1123,14 @@ def play_video(item, strm=False, force_direct=False, autoplay=False):
xlistitem.setProperty("inputstream.adaptive.license_type", item.drm)
xlistitem.setProperty("inputstream.adaptive.license_key", item.license)
xlistitem.setMimeType('application/dash+xml')
xlistitem.setProperty('inputstream.adaptive.stream_headers', httptools.get_user_agent())
elif hls or item.manifest == 'hls':# or (mediaurl.split('|')[0].endswith('m3u8') and mediaurl.startswith('http')):
if not install_inputstream():
return
xlistitem.setProperty('inputstream' if PY3 else 'inputstreamaddon', 'inputstream.adaptive')
xlistitem.setProperty('inputstream.adaptive.manifest_type', 'hls')
xlistitem.setMimeType('application/x-mpegURL')
xlistitem.setProperty('inputstream.adaptive.stream_headers', httptools.get_user_agent())
if force_direct: item.play_from = 'window'
@@ -1368,7 +1477,10 @@ def get_video_seleccionado(item, seleccion, video_urls, autoplay=False):
def set_player(item, xlistitem, mediaurl, view, strm):
logger.debug()
item.options = {'strm':False}
# logger.debug("item:\n" + item.tostring('\n'))
if item.subtitle:
if type(item.subtitle) != list: item.subtitle = [item.subtitle]
# item.subtitle.reverse()
xlistitem.setSubtitles(item.subtitle)
# Moved del conector "torrent" here
if item.server == "torrent":
@@ -1377,9 +1489,6 @@ def set_player(item, xlistitem, mediaurl, view, strm):
# If it is a strm file, play is not necessary
elif strm:
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xlistitem)
if item.subtitle:
xbmc.sleep(2000)
xbmc_player.setSubtitles(item.subtitle)
else:
if type(item.player_mode) == int:
@@ -1389,11 +1498,10 @@ def set_player(item, xlistitem, mediaurl, view, strm):
if (player_mode == 3 and mediaurl.startswith("rtmp")): player_mode = 0
elif "megacrypter.com" in mediaurl: player_mode = 3
logger.info("mediaurl=" + mediaurl)
prevent_busy()
if player_mode in [0,1]:
prevent_busy(item)
if player_mode in [1]:
item.played_time = resume_playback(get_played_time(item))
xlistitem.setProperty('StartOffset','{}'.format(resume_playback(get_played_time(item))))
logger.info('Player Mode:',['Direct', 'Bookmark'][player_mode])
# Add the listitem to a playlist
@@ -1418,26 +1526,13 @@ def set_player(item, xlistitem, mediaurl, view, strm):
download_and_play.download_and_play(mediaurl, "download_and_play.tmp", config.get_setting("downloadpath"))
return
# ALL LOOKING TO REMOVE VIEW
if item.subtitle and view:
logger.info("External subtitles: " + item.subtitle)
xbmc.sleep(2000)
xbmc_player.setSubtitles(item.subtitle)
# 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
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:
while is_playing() and xbmcgui.getCurrentWindowId() != 12006:
continue
xbmc.sleep(500)
xbmcgui.Window(12005).show()
def add_next_to_playlist(item):
import threading
@@ -1451,7 +1546,7 @@ def add_next_to_playlist(item):
nfo_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"), next.strm_path.replace('strm','nfo'))
if nfo_path and filetools.isfile(nfo_path):
head_nfo, item_nfo = videolibrarytools.read_nfo(nfo_path)
nextItem = xbmcgui.ListItem(path=item_nfo.url)
nextItem = xbmcgui.ListItem(item_nfo.fulltitle, path=item_nfo.url)
nextItem.setArt({"thumb": item_nfo.contentThumbnail if item_nfo.contentThumbnail else item_nfo.thumbnail})
set_infolabels(nextItem, item_nfo, True)
nexturl = "plugin://plugin.video.kod/?" + next.tourl()
@@ -1495,7 +1590,7 @@ def play_torrent(item, xlistitem, mediaurl):
selection = 0
if selection >= 0:
prevent_busy(item)
prevent_busy()
mediaurl = urllib.quote_plus(item.url)
torr_client = torrent_options[selection][0]
@@ -1650,7 +1745,7 @@ def get_played_time(item):
import traceback
logger.error(traceback.format_exc())
del db['viewed'][ID]
# db.close()
return played_time
@@ -1680,19 +1775,264 @@ def set_played_time(item):
import traceback
logger.error(traceback.format_exc())
del db['viewed'][ID]
db.close()
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")))
sleep = 200
def fakeVideo(sleep = False):
mediaurl = os.path.join(config.get_runtime_path(), "resources", "kod.mp4")
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=mediaurl))
while not is_playing():
xbmc.sleep(sleep)
xbmc.sleep(200)
xbmc.Player().stop()
def channelImport(channelId):
from core import filetools
ch = ''
path = filetools.join(config.get_runtime_path(), '{}', channelId + ".py")
if filetools.exists(path.format('channels')): ch = 'channels.{}'.format(channelId)
elif filetools.exists(path.format('specials')): ch = 'specials.{}'.format(channelId)
elif filetools.exists(path.format('platformcode')): ch = 'platformcode.{}'.format(channelId)
elif filetools.exists(path.format('core')): ch = 'core.{}'.format(channelId)
if ch:
channel = __import__(ch, None, None, [ch])
else:
logger.info('Channel {} not Exist'.format(channelId))
channel = None
return channel
def serverWindow(item, itemlist):
from core import db
LEFT = 1
RIGHT = 2
UP = 3
DOWN = 4
ENTER = 7
EXIT = 10
BACKSPACE = 92
CONTEXT = 117
class ServerWindow(xbmcgui.WindowXMLDialog):
def start(self, item, itemlist):
prevent_busy()
self.itemlist = itemlist
self.item = item
self.servers = []
items = []
self.selection = -1
self.actions = {}
for videoitem in self.itemlist:
videoitem.thumbnail = config.get_online_server_thumb(videoitem.server)
quality = ' [' + videoitem.quality + ']' if videoitem.quality else ''
info = ' [' + videoitem.extraInfo + ']' if videoitem.extraInfo else ''
if videoitem.server:
color = scrapertools.find_single_match(videoitem.alive, r'(FF[^\]]+)')
it = xbmcgui.ListItem('{}{}{}'.format(videoitem.serverName, quality, info))
# format Title
if videoitem.contentSeason and videoitem.contentEpisodeNumber:
title = '{}x{:02d}. {}'.format(videoitem.contentSeason, videoitem.contentEpisodeNumber, videoitem.contentTitle)
elif videoitem.contentEpisodeNumber:
title = '{:02d}. {}'.format(videoitem.contentEpisodeNumber, videoitem.contentTitle)
else:
title = videoitem.title
it.setProperties({'name': title, 'channel': videoitem.ch_name, 'color': color if color else 'FF0082C2'})
it.setArt({'poster':videoitem.contentThumbnail, 'thumb':videoitem.thumbnail, 'fanart':videoitem.contentFanart})
self.servers.append(it)
items.append(videoitem)
else:
it = xbmcgui.ListItem(videoitem.title)
if 'library' in videoitem.action:
self.actions['videolibrary'] = videoitem
if 'download' in videoitem.action:
self.actions['download'] = videoitem
self.itemlist = items
self.doModal()
return self.selection
def onInit(self):
self.SERVERS = self.getControl(100)
self.VIDEOLIBRARY = self.getControl(103)
self.DOWNLOAD = self.getControl(104)
if 'videolibrary' not in self.actions.keys():
self.VIDEOLIBRARY.setVisible(False)
if 'download' not in self.actions.keys():
self.DOWNLOAD.setVisible(False)
self.SERVERS.reset()
self.SERVERS.addItems(self.servers)
self.setFocusId(100)
# from core.support import dbg;dbg()
def onFocus(self, control):
if is_playing() and db['controls'].get('reopen', False):
self.close()
serverWindow(self.item, self.itemlist)
def onAction(self, action):
action = action.getId()
focus = self.getFocusId()
if action in [UP, DOWN, LEFT, RIGHT] and focus not in [100, 101, 102, 103, 104]:
self.setFocusId(100)
elif action in [EXIT, BACKSPACE]:
self.close()
if action in [CONTEXT]:
context(self)
def onClick(self, control):
if control == 100:
self.selection = self.itemlist[self.SERVERS.getSelectedPosition()].clone(window=True)
self.close()
elif control in [101]:
self.close()
elif control in [102]:
context(self)
elif control in [103]:
self.run(self.actions['videolibrary'])
elif control in [104]:
self.run(self.actions['download'])
def run(self, action):
from platformcode.launcher import run
run(action)
class ServerSkinWindow(xbmcgui.WindowXMLDialog):
def start(self, item, itemlist):
prevent_busy()
self.item = item
self.itemlist = itemlist
self.selection = -1
self.actions = []
self.doModal()
return self.selection
def onInit(self):
try:
self.SERVERS = self.getControl(6)
self.exit = self.getControl(5)
self.exit.setNavigation(self.exit, self.exit, self.SERVERS, self.SERVERS)
except:
pass
try: self.getControl(7).setVisible(False)
except: pass
try: self.getControl(8).setVisible(False)
except: pass
self.exit.setLabel(config.get_localized_string(60396))
for item in itemlist:
if item.server: break
if item.contentSeason and item.contentEpisodeNumber:
title = '{}x{:02d}. {}'.format(item.contentSeason, item.contentEpisodeNumber, item.contentTitle)
elif item.contentEpisodeNumber:
title = '{:02d}. {}'.format(item.contentEpisodeNumber, item.contentTitle)
else:
title = item.fulltitle
self.getControl(1).setLabel(title)
items = []
from core.support import typo
for videoitem in self.itemlist:
if videoitem.server:
logger.debug(videoitem)
videoitem.thumbnail = config.get_online_server_thumb(videoitem.server)
quality = ' [' + videoitem.quality + ']' if videoitem.quality else ''
color = scrapertools.find_single_match(videoitem.alive, r'(FF[^\]]+)')
color = typo('', 'bold color 0x{}'.format(color)) if color else ''
info = ' [' + videoitem.extraInfo + ']' if videoitem.extraInfo else ''
title = '{}{}{}{}'.format(videoitem.serverName, quality, info, color)
else:
title = videoitem.title
it = xbmcgui.ListItem(title)
if videoitem.ch_name:
it.setLabel2(videoitem.ch_name)
elif not videoitem.action:
it.setLabel2(videoitem.plot)
else:
it.setLabel2(videoitem.fulltitle)
it.setArt({'thumb': videoitem.thumbnail})
items.append(it)
self.SERVERS.reset()
self.SERVERS.addItems(items)
self.setFocus(self.SERVERS)
def onFocus(self, control):
if is_playing() and db['controls'].get('reopen', False):
self.close()
serverWindow(self.item, self.itemlist)
def onAction(self, action):
action = action.getId()
if action in [CONTEXT]:
context(self)
if action in [EXIT, BACKSPACE]:
self.close()
def onClick(self, control):
if control == 6:
self.selection = self.itemlist[self.SERVERS.getSelectedPosition()]
if not self.selection.action:
it = self.selection
self.selection = -1
dialog_textviewer(it.title, it.plot)
else:
self.close()
if control == 5:
self.close()
elif control == 7:
from platformcode.launcher import run
run(self.actions[1])
elif control == 8:
from platformcode.launcher import run
run(self.actions[0])
def context(self):
pos = self.SERVERS.getSelectedPosition()
parent = self.item
item = self.itemlist[pos]
if not item.server:
return
commands = set_context_commands(item, item.tourl(), parent)
context = [c[0] for c in commands]
context_commands = [c[1].replace('Container.Refresh', 'RunPlugin').replace('Container.Update', 'RunPlugin') for c in commands]
index = xbmcgui.Dialog().contextmenu(context)
if index > 0: xbmc.executebuiltin(context_commands[index])
if itemlist:
def monitor(itemlist):
reopen = False
while not xbmc.Monitor().abortRequested():
if not is_playing():
if reopen:
xbmc.sleep(200)
if not db['controls'].get('reopen', False):
break
if config.get_setting('window_type') == 0:
selection = ServerSkinWindow("DialogSelect.xml", config.get_runtime_path()).start(item, itemlist)
else:
selection = ServerWindow('Servers.xml', config.get_runtime_path()).start(item, itemlist)
if selection == -1:
break
else:
from platformcode.launcher import run
run(selection)
reopen = True
if not selection.server or selection.server == 'torrent': break
db.close()
logger.debug('Server Window EXIT')
import threading
threading.Thread(target=monitor, args=[itemlist]).start()

View File

@@ -33,7 +33,6 @@ def mark_auto_as_watched(item):
marked = False
sync = False
next_episode = None
show_server = True
mark_time = 0
percentage = float(config.get_setting("watched_setting")) / 100
@@ -53,22 +52,18 @@ def mark_auto_as_watched(item):
except: pass
try: total_time = xbmc.Player().getTotalTime()
except: pass
if item.played_time and xbmcgui.getCurrentWindowId() == 12005:
xbmc.Player().seekTime(item.played_time)
item.played_time = 0 # Fix for Slow Devices
mark_time = total_time * percentage
difference = total_time - actual_time
# Mark as Watched
if actual_time > mark_time and not marked:
if mark_time and total_time > actual_time > mark_time and not marked:
logger.info("Marked as Watched")
item.playcount = 1
marked = True
item.played_time = 0
platformtools.set_played_time(item)
if item.options['strm'] : sync = True
show_server = False
from specials import videolibrary
videolibrary.mark_content_as_watched2(item)
if not next_episode:
@@ -86,9 +81,16 @@ def mark_auto_as_watched(item):
break
# if item.options['continue']:
if actual_time < mark_time and mark_time:
from core import db
if marked:
logger.debug('CLOSE')
item.played_time = 0
db['controls']['reopen'] = False
else:
logger.debug('REOPEN')
item.played_time = actual_time
else: item.played_time = 0
db['controls']['reopen'] = True
db.close()
platformtools.set_played_time(item)
# Silent sync with Trakt
@@ -97,23 +99,14 @@ def mark_auto_as_watched(item):
while platformtools.is_playing():
xbmc.sleep(100)
if not show_server and item.play_from != 'window' and not item.no_return:
xbmc.sleep(700)
xbmc.executebuiltin('Action(ParentDir)')
xbmc.sleep(500)
if next_episode and next_episode.next_ep and config.get_setting('next_ep') < 3:
from platformcode.launcher import run
run(next_episode)
# db need to be closed when not used, it will cause freezes
from core import db
db.close()
# If it is configured to mark as seen
if config.get_setting("mark_as_watched", "videolibrary"):
threading.Thread(target=mark_as_watched_subThread, args=[item]).start()
logger.debug('EXIT MONITOR')
def sync_trakt_addon(path_folder):
"""