1145 lines
51 KiB
Python
1145 lines
51 KiB
Python
# -*- coding: utf-8 -*-
|
|
# ------------------------------------------------------------
|
|
# Download manager
|
|
# ------------------------------------------------------------
|
|
|
|
from __future__ import division
|
|
#from builtins import str
|
|
import sys, os
|
|
PY3 = False
|
|
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
|
from past.utils import old_div
|
|
|
|
import re, time, unicodedata, xbmc
|
|
|
|
from channelselector import get_thumb
|
|
from core import filetools, jsontools, scraper, scrapertools, servertools, videolibrarytools, support
|
|
from core.downloader import Downloader
|
|
from core.item import Item
|
|
from platformcode import config, logger, platformtools
|
|
from core.support import info, typo
|
|
from servers import torrent
|
|
|
|
kb = '0xFF65B3DA'
|
|
kg = '0xFF65DAA8'
|
|
kr = '0xFFDA6865'
|
|
ky = '0xFFDAAB65'
|
|
|
|
STATUS_COLORS = {0: '', 1: '', 2: kg, 3: kr, 4: kb}
|
|
STATUS_CODES = type("StatusCode", (), {"stoped": 0, "canceled": 1, "completed": 2, "error": 3, "downloading": 4 })
|
|
DOWNLOAD_LIST_PATH = config.get_setting("downloadlistpath")
|
|
DOWNLOAD_PATH = config.get_setting("downloadpath")
|
|
STATS_FILE = filetools.join(config.get_data_path(), "servers.json")
|
|
|
|
FOLDER_MOVIES = config.get_setting("folder_movies")
|
|
FOLDER_TVSHOWS = config.get_setting("folder_tvshows")
|
|
TITLE_FILE = "[COLOR %s]| %i%% |[/COLOR] - %s"
|
|
TITLE_TVSHOW = "[COLOR %s]| %i%% |[/COLOR] - %s [%s]"
|
|
extensions_list = ['.aaf', '.3gp', '.asf', '.avi', '.flv', '.mpeg', '.m1v', '.m2v', '.m4v', '.mkv', '.mov', '.mpg', '.mpe', '.mp4', '.ogg', '.wmv']
|
|
|
|
|
|
def mainlist(item):
|
|
info()
|
|
itemlist = []
|
|
|
|
# File list
|
|
for file in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
# We skip all the non JSON
|
|
if not file.endswith(".json"): continue
|
|
|
|
# we load the item
|
|
file = filetools.join(DOWNLOAD_LIST_PATH, file)
|
|
i = Item(path=file).fromjson(filetools.read(file))
|
|
i.thumbnail = i.contentThumbnail
|
|
|
|
# Main listing
|
|
if not item.contentType == "tvshow":
|
|
# Series
|
|
if i.contentType == "episode":
|
|
# We check that the series is not already in the itemlist
|
|
if not [x for x in itemlist if x.contentSerieName == i.contentSerieName and x.contentChannel == i.contentChannel]:
|
|
|
|
title = TITLE_TVSHOW % (STATUS_COLORS[i.downloadStatus], i.downloadProgress, i.contentSerieName, i.contentChannel)
|
|
|
|
itemlist.append(Item(title=title, channel="downloads", action="mainlist", contentType="tvshow",
|
|
contentSerieName=i.contentSerieName, contentChannel=i.contentChannel,
|
|
downloadStatus=i.downloadStatus, downloadProgress=[i.downloadProgress],
|
|
fanart=i.fanart, thumbnail=i.thumbnail))
|
|
|
|
else:
|
|
s = [x for x in itemlist if x.contentSerieName == i.contentSerieName and x.contentChannel == i.contentChannel][0]
|
|
s.downloadProgress.append(i.downloadProgress)
|
|
downloadProgress = old_div(sum(s.downloadProgress), len(s.downloadProgress))
|
|
|
|
if not s.downloadStatus in [STATUS_CODES.error, STATUS_CODES.canceled] and not i.downloadStatus in [
|
|
STATUS_CODES.completed, STATUS_CODES.stoped]:
|
|
s.downloadStatus = i.downloadStatus
|
|
|
|
s.title = TITLE_TVSHOW % (STATUS_COLORS[s.downloadStatus], downloadProgress, i.contentSerieName, i.contentChannel)
|
|
|
|
# Movies
|
|
elif i.contentType == "movie" or i.contentType == "video":
|
|
i.title = TITLE_FILE % (STATUS_COLORS[i.downloadStatus], i.downloadProgress, i.contentTitle)
|
|
itemlist.append(i)
|
|
|
|
# Listed within a series
|
|
else:
|
|
if i.contentType == "episode" and i.contentSerieName == item.contentSerieName and i.contentChannel == item.contentChannel:
|
|
i.title = TITLE_FILE % (STATUS_COLORS[i.downloadStatus], i.downloadProgress, "%dx%0.2d: %s" % (i.contentSeason, i.contentEpisodeNumber, i.contentTitle))
|
|
itemlist.append(i)
|
|
|
|
estados = [i.downloadStatus for i in itemlist]
|
|
|
|
# If there is any completed
|
|
if 2 in estados:
|
|
itemlist.insert(0, Item(channel=item.channel, action="clean_ready", title=config.get_localized_string(70218),
|
|
contentType=item.contentType, contentChannel=item.contentChannel, thumbnail=get_thumb('delete.png'),
|
|
contentSerieName=item.contentSerieName, text_color=STATUS_COLORS[STATUS_CODES.completed]))
|
|
|
|
# If there is any error
|
|
if 3 in estados:
|
|
itemlist.insert(0, Item(channel=item.channel, action="restart_error", title=config.get_localized_string(70219),
|
|
contentType=item.contentType, contentChannel=item.contentChannel, thumbnail=get_thumb('update.png'),
|
|
contentSerieName=item.contentSerieName, text_color=STATUS_COLORS[STATUS_CODES.error]))
|
|
|
|
# If there is any pending
|
|
if 1 in estados or 0 in estados:
|
|
itemlist.insert(0, Item(channel=item.channel, action="download_all", title=support.typo(config.get_localized_string(70220),'bold'),
|
|
contentType=item.contentType, contentChannel=item.contentChannel, thumbnail=get_thumb('downloads.png'),
|
|
contentSerieName=item.contentSerieName))
|
|
|
|
if len(itemlist):
|
|
itemlist.insert(0, Item(channel=item.channel, action="clean_all", title=support.typo(config.get_localized_string(70221),'bold'),
|
|
contentType=item.contentType, contentChannel=item.contentChannel, thumbnail=get_thumb('delete.png'),
|
|
contentSerieName=item.contentSerieName))
|
|
|
|
# if there's at least one downloading
|
|
if 4 in estados:
|
|
itemlist.insert(0, Item(channel=item.channel, action="stop_all", title=config.get_localized_string(60222),
|
|
contentType=item.contentType, contentChannel=item.contentChannel,
|
|
contentSerieName=item.contentSerieName, thumbnail=get_thumb('stop.png'),
|
|
text_color=STATUS_COLORS[STATUS_CODES.downloading]))
|
|
|
|
if not item.contentType == "tvshow" and config.get_setting("browser") == True:
|
|
itemlist.insert(0, Item(channel=item.channel, action="browser", title=support.typo(config.get_localized_string(70222),'bold'), thumbnail=get_thumb('search.png'), url=DOWNLOAD_PATH))
|
|
|
|
if not item.contentType == "tvshow":
|
|
itemlist.append(Item(channel='shortcuts', action="SettingOnPosition", category=6, setting=0, title= support.typo(config.get_localized_string(70288),'bold color kod'), thumbnail=get_thumb('setting_0.png')))
|
|
|
|
# Reload
|
|
if estados:
|
|
itemlist.insert(0, Item(channel=item.channel, action="reload", title= support.typo(config.get_localized_string(70008),'bold color kod'),
|
|
contentType=item.contentType, contentChannel=item.contentChannel, thumbnail=get_thumb('update.png'),
|
|
contentSerieName=item.contentSerieName))
|
|
|
|
return itemlist
|
|
|
|
|
|
def settings(item):
|
|
ret = platformtools.show_channel_settings(caption=config.get_localized_string(70224))
|
|
platformtools.itemlist_refresh()
|
|
return ret
|
|
|
|
|
|
def browser(item):
|
|
info()
|
|
itemlist = []
|
|
|
|
for file in filetools.listdir(item.url):
|
|
if file == "list": continue
|
|
if filetools.isdir(filetools.join(item.url, file)):
|
|
itemlist.append(Item(channel=item.channel, title=file, action=item.action, url=filetools.join(item.url, file), context=[{ 'title': config.get_localized_string(30037), 'channel': 'downloads', 'action': "del_dir"}]))
|
|
else:
|
|
if not item.infoLabels:
|
|
infoLabels = {"mediatype":"video"}
|
|
else:
|
|
infoLabels = item.infoLabels
|
|
itemlist.append(Item(channel=item.channel, title=file, action="play", infoLabels=infoLabels, url=filetools.join(item.url, file), context=[{ 'title': config.get_localized_string(30039), 'channel': 'downloads', 'action': "del_file"}]))
|
|
|
|
return itemlist
|
|
|
|
|
|
def del_file(item):
|
|
ok = platformtools.dialog_yesno(config.get_localized_string(30039),config.get_localized_string(30040) % item.title)
|
|
if ok:
|
|
filetools.remove(item.url)
|
|
xbmc.sleep(100)
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def del_dir(item):
|
|
ok = platformtools.dialog_yesno(config.get_localized_string(30037),config.get_localized_string(30038))
|
|
if ok:
|
|
filetools.rmdirtree(item.url)
|
|
xbmc.sleep(100)
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def clean_all(item):
|
|
info()
|
|
stop_all()
|
|
removeFiles = False
|
|
if platformtools.dialog_yesno(config.get_localized_string(20000), config.get_localized_string(30300)):
|
|
removeFiles = True
|
|
|
|
for File in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
if File.endswith(".json"):
|
|
download_item = Item().fromjson(filetools.read(filetools.join(DOWNLOAD_LIST_PATH, File)))
|
|
if not item.contentType == "tvshow" or ( item.contentSerieName == download_item.contentSerieName and item.contentChannel == download_item.contentChannel):
|
|
filetools.remove(filetools.join(DOWNLOAD_LIST_PATH, File))
|
|
if removeFiles:
|
|
filetools.remove(filetools.join(DOWNLOAD_PATH, download_item.downloadFilename))
|
|
dirName = filetools.join(DOWNLOAD_PATH, filetools.dirname(download_item.downloadFilename))
|
|
if len(filetools.listdir(dirName)) == 0:
|
|
filetools.rmdir(dirName)
|
|
|
|
xbmc.sleep(100)
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def reload(item):
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def stop_all(item=None):
|
|
info()
|
|
|
|
for fichero in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
if fichero.endswith(".json"):
|
|
download_item = Item().fromjson(filetools.read(filetools.join(DOWNLOAD_LIST_PATH, fichero)))
|
|
if download_item.TorrentName:
|
|
from inspect import stack
|
|
if stack()[1][3] == 'clean_all': action = 'delete'
|
|
else: action = 'pause'
|
|
torrent.elementum_actions(action, download_item.TorrentName)
|
|
if download_item.downloadStatus == 4:
|
|
update_json(filetools.join(DOWNLOAD_LIST_PATH, fichero), {"downloadStatus": STATUS_CODES.stoped})
|
|
xbmc.sleep(300)
|
|
if item:
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def clean_ready(item):
|
|
info()
|
|
for fichero in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
if fichero.endswith(".json"):
|
|
download_item = Item().fromjson(filetools.read(filetools.join(DOWNLOAD_LIST_PATH, fichero)))
|
|
if not item.contentType == "tvshow" or ( item.contentSerieName == download_item.contentSerieName and item.contentChannel == download_item.contentChannel):
|
|
if download_item.downloadStatus == STATUS_CODES.completed:
|
|
filetools.remove(filetools.join(DOWNLOAD_LIST_PATH, fichero))
|
|
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def restart_error(item):
|
|
info()
|
|
for fichero in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
if fichero.endswith(".json"):
|
|
download_item = Item().fromjson(filetools.read(filetools.join(DOWNLOAD_LIST_PATH, fichero)))
|
|
|
|
if not item.contentType == "tvshow" or ( item.contentSerieName == download_item.contentSerieName and item.contentChannel == download_item.contentChannel):
|
|
if download_item.downloadStatus == STATUS_CODES.error:
|
|
if filetools.isfile(
|
|
filetools.join(DOWNLOAD_PATH, download_item.downloadFilename)):
|
|
filetools.remove(
|
|
filetools.join(DOWNLOAD_PATH, download_item.downloadFilename))
|
|
|
|
update_json(item.path, {"downloadStatus": STATUS_CODES.stoped, "downloadComplete": 0, "downloadProgress": 0})
|
|
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def download_all(item):
|
|
time.sleep(0.5)
|
|
item.action = "download_all_background"
|
|
xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")")
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def download_all_background(item):
|
|
for fichero in sorted(filetools.listdir(DOWNLOAD_LIST_PATH)):
|
|
if fichero.endswith(".json"):
|
|
download_item = Item(path=filetools.join(DOWNLOAD_LIST_PATH, fichero)).fromjson(
|
|
filetools.read(filetools.join(DOWNLOAD_LIST_PATH, fichero)))
|
|
|
|
if not item.contentType == "tvshow" or ( item.contentSerieName == download_item.contentSerieName and item.contentChannel == download_item.contentChannel):
|
|
if download_item.downloadStatus in [STATUS_CODES.stoped, STATUS_CODES.canceled]:
|
|
res = start_download(download_item)
|
|
# platformtools.itemlist_refresh()
|
|
# If canceled, we stop
|
|
if res == STATUS_CODES.canceled: break
|
|
|
|
|
|
def menu(item):
|
|
info(item)
|
|
if item.downloadServer:
|
|
servidor = item.downloadServer.get("server", "Auto")
|
|
else:
|
|
servidor = "Auto"
|
|
# Options available for the menu
|
|
op = [config.get_localized_string(70225), config.get_localized_string(70226), config.get_localized_string(70227),
|
|
config.get_localized_string(30165) % (servidor.capitalize()), config.get_localized_string(60220),
|
|
config.get_localized_string(60221)]
|
|
|
|
opciones = []
|
|
|
|
# Options for the menu
|
|
if item.downloadStatus == STATUS_CODES.stoped:
|
|
opciones.append(op[0]) # Download
|
|
if not item.server: opciones.append(op[3]) # Choose Server
|
|
opciones.append(op[1]) # Remove from the list
|
|
|
|
if item.downloadStatus == STATUS_CODES.canceled:
|
|
opciones.append(op[0]) # Download
|
|
if not item.server: opciones.append(op[3]) # Choose Server
|
|
opciones.append(op[2]) # Restart download
|
|
opciones.append(op[1]) # Remove from the list
|
|
|
|
if item.downloadStatus == STATUS_CODES.completed:
|
|
opciones.append(op[5]) # Play
|
|
opciones.append(op[1]) # Remove from the list
|
|
opciones.append(op[2]) # Restart download
|
|
|
|
if item.downloadStatus == STATUS_CODES.error: # Download with error
|
|
opciones.append(op[2]) # Restart download
|
|
opciones.append(op[1]) # Remove from the list
|
|
|
|
if item.downloadStatus == STATUS_CODES.downloading:
|
|
opciones.append(op[5]) # Play
|
|
opciones.append(op[4]) # Pause Download
|
|
opciones.append(op[1]) # Remove from the list
|
|
|
|
# Show Dialog
|
|
seleccion = platformtools.dialog_select(config.get_localized_string(30163), opciones)
|
|
logger.debug('SELECTION: '+ op[seleccion])
|
|
|
|
# -1 is cancel
|
|
if seleccion == -1: return
|
|
|
|
# Delete
|
|
if opciones[seleccion] == op[1]:
|
|
filetools.remove(item.path)
|
|
if item.TorrentName:
|
|
torrent.elementum_actions('delete', item.TorrentName)
|
|
else:
|
|
if platformtools.dialog_yesno(config.get_localized_string(20000), config.get_localized_string(30300)):
|
|
filetools.remove(filetools.join(DOWNLOAD_PATH, item.downloadFilename))
|
|
|
|
# Start Download
|
|
if opciones[seleccion] == op[0]:
|
|
item.action = "start_download"
|
|
xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")")
|
|
|
|
# Select Server
|
|
if opciones[seleccion] == op[3]:
|
|
select_server(item)
|
|
|
|
# Restart Download
|
|
if opciones[seleccion] == op[2]:
|
|
if filetools.isfile(filetools.join(DOWNLOAD_PATH, item.downloadFilename)):
|
|
filetools.remove(filetools.join(DOWNLOAD_PATH, item.downloadFilename))
|
|
|
|
update_json(item.path, {"downloadStatus": STATUS_CODES.stoped, "downloadComplete": 0, "downloadProgress": 0, "downloadServer": {}})
|
|
|
|
if opciones[seleccion] == op[4]:
|
|
if item.TorrentName:
|
|
torrent.elementum_actions('pause', item.TorrentName)
|
|
update_json(item.path, {"downloadStatus": STATUS_CODES.stoped})
|
|
|
|
if opciones[seleccion] == op[5]:
|
|
path = filetools.join(DOWNLOAD_PATH, item.downloadFilename)
|
|
if filetools.isdir(path):
|
|
videos = []
|
|
files = filetools.listdir(path)
|
|
for f in files:
|
|
if os.path.splitext(f)[-1] in extensions_list:
|
|
videos.append(f)
|
|
if len(videos) > 1:
|
|
selection = platformtools.dialog_select(config.get_localized_string(30034), files)
|
|
else:
|
|
selection = 0
|
|
xbmc.executebuiltin('PlayMedia(' + filetools.join(path, files[selection]) + ',resume)')
|
|
else:
|
|
xbmc.executebuiltin('PlayMedia(' + path + ',resume)')
|
|
|
|
if opciones[seleccion] != op[5]:
|
|
platformtools.itemlist_refresh()
|
|
|
|
|
|
def move_to_libray(item):
|
|
info()
|
|
|
|
if item.contentType == 'movie':
|
|
FOLDER = FOLDER_MOVIES
|
|
path_title = "%s [%s]" % (item.contentTitle.strip() if item.contentTitle else item.fulltitle.strip() , item.infoLabels['IMDBNumber'])
|
|
move_path = filetools.join(config.get_videolibrary_path(), FOLDER, path_title)
|
|
|
|
else:
|
|
FOLDER = FOLDER_TVSHOWS
|
|
path_title = os.path.dirname(item.downloadFilename)
|
|
move_path = filetools.join(config.get_videolibrary_path(), FOLDER)
|
|
|
|
download_path = filetools.join(DOWNLOAD_PATH, item.downloadFilename)
|
|
library_path = filetools.join(move_path, *filetools.split(item.downloadFilename))
|
|
final_path = download_path
|
|
|
|
if not filetools.isdir(filetools.dirname(library_path)):
|
|
filetools.mkdir(filetools.dirname(library_path))
|
|
|
|
if item.contentType == "movie" and item.infoLabels["tmdb_id"]:
|
|
contentTitle = item.contentTitle if item.contentTitle else item.fulltitle
|
|
library_item = Item(title= filetools.split(item.downloadFilename)[-1], channel="downloads", contentTitle = contentTitle,
|
|
fulltitle = item.fulltitle,action="findvideos", infoLabels=item.infoLabels, url=library_path)
|
|
videolibrarytools.save_movie(library_item, silent=True)
|
|
|
|
elif item.contentType == "episode" and item.infoLabels["tmdb_id"]:
|
|
contentSerieName = item.contentSerieName if item.contentSerieName else item.fulltitle
|
|
library_item = Item(title=filetools.split(item.downloadFilename)[-1], channel="downloads", contentSerieName = contentSerieName,
|
|
fulltitle = item.fulltitle, action="findvideos", infoLabels=item.infoLabels, url=library_path)
|
|
tvshow = Item(channel="downloads", contentType="tvshow", contentSerieName = contentSerieName,
|
|
fulltitle = item.fulltitle, infoLabels={"tmdb_id": item.infoLabels["tmdb_id"]})
|
|
videolibrarytools.save_tvshow(tvshow, [library_item], silent=True)
|
|
|
|
if filetools.isfile(library_path) and filetools.isfile(download_path):
|
|
filetools.remove(library_path)
|
|
|
|
if filetools.isfile(download_path):
|
|
if filetools.move(download_path, library_path, silent=True):
|
|
final_path = library_path
|
|
|
|
if len(filetools.listdir(filetools.dirname(download_path))) == 0:
|
|
filetools.rmdir(filetools.dirname(download_path))
|
|
|
|
name = item.contentTitle if item.contentType == 'movie' else str(item.infoLabels['season']) + 'x' + str(item.infoLabels['episode']).zfill(2)
|
|
list_item = filetools.listdir(filetools.join(config.get_videolibrary_path(), FOLDER, path_title))
|
|
|
|
clean = False
|
|
for File in list_item:
|
|
filename = File.lower()
|
|
name = name.lower()
|
|
|
|
if filename.startswith(name) and (filename.endswith('.strm') or (filename.endswith('.json') and 'downloads' not in filename)):
|
|
clean = True
|
|
file_path = filetools.join(config.get_setting("videolibrarypath"), FOLDER, path_title, File)
|
|
info('Delete File:', str(file_path))
|
|
filetools.remove(file_path)
|
|
if file_path.endswith('.strm'):
|
|
file_strm_path = file_path
|
|
|
|
if config.is_xbmc() and config.get_setting("videolibrary_kodi"):
|
|
from platformcode import xbmc_videolibrary
|
|
if clean == True:
|
|
path_list = [file_strm_path]
|
|
xbmc_videolibrary.clean(path_list)
|
|
xbmc_videolibrary.update(FOLDER, path_title)
|
|
|
|
|
|
def update_json(path, params):
|
|
item = Item().fromjson(filetools.read(path))
|
|
item.__dict__.update(params)
|
|
filetools.write(path, item.tojson())
|
|
|
|
|
|
def save_server_statistics(server, speed, success):
|
|
if filetools.isfile(STATS_FILE):
|
|
servers = jsontools.load(filetools.read(STATS_FILE))
|
|
else:
|
|
servers = {}
|
|
|
|
if not server in servers:
|
|
servers[server] = {"success": [], "count": 0, "speeds": [], "last": 0}
|
|
|
|
servers[server]["count"] += 1
|
|
servers[server]["success"].append(bool(success))
|
|
servers[server]["success"] = servers[server]["success"][-5:]
|
|
servers[server]["last"] = time.time()
|
|
if success:
|
|
servers[server]["speeds"].append(speed)
|
|
servers[server]["speeds"] = servers[server]["speeds"][-5:]
|
|
|
|
filetools.write(STATS_FILE, jsontools.dump(servers))
|
|
return
|
|
|
|
|
|
def get_server_position(server):
|
|
if filetools.isfile(STATS_FILE):
|
|
servers = jsontools.load(filetools.read(STATS_FILE))
|
|
else:
|
|
servers = {}
|
|
|
|
if server in servers:
|
|
pos = [s for s in sorted(servers, key=lambda x: (old_div(sum(servers[x]["speeds"]), (len(servers[x]["speeds"]) or 1)), float(sum(servers[x]["success"])) / ( len(servers[x]["success"]) or 1)), reverse=True)]
|
|
return pos.index(server) + 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
def get_match_list(data, match_list, order_list=None, only_ascii=False, ignorecase=False):
|
|
"""
|
|
Search for matches in a text string, with a dictionary of "ID" / "List of search strings":
|
|
{"ID1": ["String 1", "String 2", "String 3"],
|
|
"ID2": ["String 4", "String 5", "String 6"]
|
|
}
|
|
|
|
The dictionary could not contain the same search string in several IDs.
|
|
The search is performed in order of search string size (from longest to shortest) if a string matches,
|
|
it is removed from the search string for the following, so that two categories are not detected if one string is part of another:
|
|
for example: "Spanish Language" and "Spanish" if the first appears in the string "Pablo knows how to speak the Spanish Language"
|
|
It will match "Spanish Language" but not "Spanish" since the longest match has priority.
|
|
|
|
"""
|
|
match_dict = dict()
|
|
matches = []
|
|
|
|
# We pass the string to unicode
|
|
if not PY3:
|
|
data = unicode(data, "utf8")
|
|
|
|
# We pass the dictionary to {"String 1": "ID1", "String 2", "ID1", "String 4", "ID2"} and we pass them to unicode
|
|
for key in match_list:
|
|
if order_list and not key in order_list:
|
|
raise Exception("key '%s' not in match_list" % key)
|
|
for value in match_list[key]:
|
|
if value in match_dict:
|
|
raise Exception("Duplicate word in list: '%s'" % value)
|
|
if not PY3:
|
|
match_dict[unicode(value, "utf8")] = key
|
|
else:
|
|
match_dict[value] = key
|
|
|
|
# If ignorecase = True, we pass everything to capital letters
|
|
if ignorecase:
|
|
data = data.upper()
|
|
match_dict = dict((key.upper(), match_dict[key]) for key in match_dict)
|
|
|
|
# If ascii = True, we remove all accents and Ñ
|
|
if only_ascii:
|
|
data = ''.join((c for c in unicodedata.normalize('NFD', data) if unicodedata.category(c) != 'Mn'))
|
|
match_dict = dict((''.join((c for c in unicodedata.normalize('NFD', key) if unicodedata.category(c) != 'Mn')), match_dict[key]) for key in match_dict)
|
|
|
|
# We sort the list from largest to smallest and search.
|
|
for match in sorted(match_dict, key=lambda x: len(x), reverse=True):
|
|
s = data
|
|
for a in matches:
|
|
s = s.replace(a, "")
|
|
if match in s:
|
|
matches.append(match)
|
|
if matches:
|
|
if order_list:
|
|
return type("Mtch_list", (), {"key": match_dict[matches[-1]], "index": order_list.index(match_dict[matches[-1]])})
|
|
else:
|
|
return type("Mtch_list", (), {"key": match_dict[matches[-1]], "index": None})
|
|
else:
|
|
if order_list:
|
|
return type("Mtch_list", (), {"key": None, "index": len(order_list)})
|
|
else:
|
|
return type("Mtch_list", (), {"key": None, "index": None})
|
|
|
|
|
|
def sort_method(item):
|
|
"""
|
|
Score each item based on various parameters:
|
|
@type item: item
|
|
@param item: item to be valued.
|
|
@return: punctuation obtained
|
|
@rtype: int
|
|
"""
|
|
lang_orders = {}
|
|
lang_orders['ITA'] = ["ITA", "Sub-ITA"]
|
|
lang_orders['Sub-ITA'] = ["ITA", "Sub-ITA"]
|
|
|
|
quality_orders = {}
|
|
quality_orders[0] = ["BLURAY", "FULLHD", "HD", "480P", "360P", "240P"]
|
|
quality_orders[1] = ["FULLHD", "HD", "480P", "360P", "240P", "BLURAY"]
|
|
quality_orders[2] = ["HD", "480P", "360P", "240P", "FULLHD", "BLURAY"]
|
|
quality_orders[3] = ["480P", "360P", "240P", "BLURAY", "FULLHD", "HD"]
|
|
|
|
order_list_idiomas = lang_orders[config.get_setting("language")]
|
|
match_list_idimas = {"ITA": ["ITA", "IT", "Italiano", "italiano", "ITALIANO"],
|
|
"Sub-ITA": ["Sottotitolato", "SUB", "sub-ita", "SUB-ITA", "Sub-ITA", "Sub-Ita"]}
|
|
|
|
order_list_calidad = ["BLURAY", "FULLHD", "HD", "480P", "360P", "240P"]
|
|
order_list_calidad = quality_orders[int(config.get_setting("quality"))]
|
|
match_list_calidad = {"BLURAY": ["BR", "BLURAY", '4K'],
|
|
"FULLHD": ["FULLHD", "FULL HD", "1080", "HD1080", "HD 1080", "1080p"],
|
|
"HD": ["HD", "HD REAL", "HD 720", "720", "HDTV", "720p"],
|
|
"480P": ["SD", "480P", '480', 'NORMAL'],
|
|
"360P": ["360P", "360", 'MOBILE'],
|
|
"240P": ["240P", "240"]}
|
|
|
|
value = (get_match_list(item.title, match_list_idimas, order_list_idiomas, ignorecase=True, only_ascii=True).index, \
|
|
get_match_list(item.title, match_list_calidad, order_list_calidad, ignorecase=True, only_ascii=True).index)
|
|
|
|
if config.get_setting("server_speed"):
|
|
value += tuple([get_server_position(item.server)])
|
|
|
|
return value
|
|
|
|
|
|
def download_from_url(url, item):
|
|
info("Attempting to download:", url)
|
|
if '.m3u8' in url.lower().split('|')[0] or url.lower().startswith("rtmp"):
|
|
save_server_statistics(item.server, 0, False)
|
|
platformtools.dialog_notification('m3u8 Download',config.get_localized_string(60364), sound=False)
|
|
return {"downloadStatus": STATUS_CODES.error}
|
|
|
|
# We get the download path and the file name
|
|
item.downloadFilename = item.downloadFilename
|
|
download_path = filetools.dirname(filetools.join(DOWNLOAD_PATH, item.downloadFilename))
|
|
file_name = filetools.basename(filetools.join(DOWNLOAD_PATH, item.downloadFilename))
|
|
|
|
# We create the folder if it does not exist
|
|
|
|
if not filetools.exists(download_path):
|
|
filetools.mkdir(download_path)
|
|
|
|
# We launch the download
|
|
d = Downloader(url, download_path, file_name,
|
|
max_connections=1 + int(config.get_setting("max_connections", "downloads")),
|
|
block_size=2 ** (17 + int(config.get_setting("block_size", "downloads"))),
|
|
part_size=2 ** (20 + int(config.get_setting("part_size", "downloads"))),
|
|
max_buffer=2 * int(config.get_setting("max_buffer", "downloads")),
|
|
json_path=item.path)
|
|
dir = filetools.dirname(item.downloadFilename)
|
|
file = filetools.join(dir, d.filename)
|
|
|
|
update_json(item.path, {"downloadUrl": d.download_url, "downloadStatus": STATUS_CODES.downloading, "downloadSize": d.size[0],
|
|
"downloadProgress": d.progress, "downloadCompleted": d.downloaded[0], "downloadFilename": file})
|
|
|
|
d.start_dialog(config.get_localized_string(60332))
|
|
|
|
# Download stopped. We get the state:
|
|
# Download failed
|
|
if d.state == d.states.error:
|
|
info("Error trying to download", url)
|
|
status = STATUS_CODES.error
|
|
|
|
# Download has stopped
|
|
elif d.state == d.states.stopped:
|
|
info("Stop download")
|
|
status = STATUS_CODES.canceled
|
|
|
|
# Download is complete
|
|
elif d.state == d.states.completed:
|
|
info("Downloaded correctly")
|
|
status = STATUS_CODES.completed
|
|
|
|
if (item.downloadSize and item.downloadSize != d.size[0]) or d.size[0] < 5000000: # if size don't correspond or file is too little (gounlimited for example send a little video to say the server is overloaded)
|
|
status = STATUS_CODES.error
|
|
|
|
save_server_statistics(item.server, d.speed[0], d.state != d.states.error)
|
|
|
|
if status == STATUS_CODES.completed and config.get_setting("library_move"):
|
|
move_to_libray(item.clone(downloadFilename=file))
|
|
|
|
return {"downloadUrl": d.download_url, "downloadStatus": status, "downloadSize": d.size[0],
|
|
"downloadProgress": d.progress, "downloadCompleted": d.downloaded[0], "downloadFilename": file}
|
|
|
|
|
|
def download_from_server(item):
|
|
info(item.tostring())
|
|
unsupported_servers = ["torrent"]
|
|
|
|
if item.contentChannel == 'local':
|
|
return {"downloadStatus": STATUS_CODES.completed}
|
|
|
|
progreso = platformtools.dialog_progress_bg(config.get_localized_string(30101), config.get_localized_string(70178) % item.server)
|
|
|
|
try:
|
|
if item.contentChannel in ['community', 'videolibrary']:
|
|
channel = __import__('specials.%s' % item.contentChannel, None, None, ['specials.%s' % item.contentChannel])
|
|
else:
|
|
channel = __import__('channels.%s' % item.contentChannel, None, None, ['channels.%s' % item.contentChannel])
|
|
if hasattr(channel, "play") and not item.play_menu:
|
|
|
|
progreso.update(50, config.get_localized_string(70178) % item.server + '\n' + config.get_localized_string(70180) % item.contentChannel)
|
|
try:
|
|
itemlist = getattr(channel, "play")(item.clone(channel=item.contentChannel, action=item.contentAction))
|
|
except:
|
|
logger.error("Error in the channel %s" % item.contentChannel)
|
|
else:
|
|
if len(itemlist) and isinstance(itemlist[0], Item):
|
|
download_item = item.clone(**itemlist[0].__dict__)
|
|
download_item.contentAction = download_item.action
|
|
download_item.infoLabels = item.infoLabels
|
|
item = download_item
|
|
elif len(itemlist) and isinstance(itemlist[0], list):
|
|
item.video_urls = itemlist
|
|
if not item.server: item.server = "directo"
|
|
else:
|
|
info("There is nothing to reproduce")
|
|
return {"downloadStatus": STATUS_CODES.error}
|
|
finally:
|
|
progreso.close()
|
|
info("contentAction: %s | contentChannel: %s | server: %s | url: %s" % (item.contentAction, item.contentChannel, item.server, item.url))
|
|
|
|
if item.server == 'torrent':
|
|
import xbmcgui
|
|
xlistitem = xbmcgui.ListItem(path=item.url)
|
|
xlistitem.setArt({'icon': item.thumbnail, 'thumb': item.thumbnail, 'poster': item.thumbnail, 'fanart': item.thumbnail})
|
|
platformtools.set_infolabels(xlistitem, item)
|
|
platformtools.play_torrent(item, xlistitem, item.url)
|
|
|
|
if not item.server or not item.url or not item.contentAction == "play" or item.server in unsupported_servers:
|
|
logger.error("The Item does not contain the necessary parameters.")
|
|
return {"downloadStatus": STATUS_CODES.error}
|
|
|
|
if not item.video_urls:
|
|
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(item.server, item.url, item.password, True, True)
|
|
else:
|
|
video_urls, puedes, motivo = item.video_urls, True, ""
|
|
|
|
# If it is not available, we go out
|
|
if not puedes:
|
|
info("The video is NOT available")
|
|
return {"downloadStatus": STATUS_CODES.error}
|
|
|
|
else:
|
|
info("YES Video is available")
|
|
|
|
result = {}
|
|
|
|
# Go through all the options until I can download one correctly
|
|
for video_url in reversed(video_urls):
|
|
|
|
result = download_from_url(video_url[1], item)
|
|
|
|
if result["downloadStatus"] in [STATUS_CODES.canceled, STATUS_CODES.completed]:
|
|
break
|
|
|
|
# Download error, we continue with the next option
|
|
if result["downloadStatus"] == STATUS_CODES.error:
|
|
continue
|
|
|
|
# We return the state
|
|
return result
|
|
|
|
|
|
def download_from_best_server(item):
|
|
info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url))
|
|
|
|
result = {"downloadStatus": STATUS_CODES.error}
|
|
progreso = platformtools.dialog_progress_bg(config.get_localized_string(30101), config.get_localized_string(70179))
|
|
|
|
try:
|
|
if item.downloadItemlist:
|
|
info('using cached servers')
|
|
play_items = [Item().fromurl(i) for i in item.downloadItemlist]
|
|
else:
|
|
if item.contentChannel in ['community', 'videolibrary']:
|
|
channel = __import__('specials.%s' % item.contentChannel, None, None, ['specials.%s' % item.contentChannel])
|
|
else:
|
|
channel = __import__('channels.%s' % item.contentChannel, None, None, ['channels.%s' % item.contentChannel])
|
|
|
|
progreso.update(50, config.get_localized_string(70184) + '\n' + config.get_localized_string(70180) % item.contentChannel)
|
|
|
|
if hasattr(channel, item.contentAction):
|
|
play_items = getattr(channel, item.contentAction)(item.clone(action=item.contentAction, channel=item.contentChannel))
|
|
else:
|
|
play_items = servertools.find_video_items(item.clone(action=item.contentAction, channel=item.contentChannel))
|
|
|
|
play_items = [x for x in play_items if x.action == "play" and not "trailer" in x.title.lower()]
|
|
|
|
progreso.update(100, config.get_localized_string(70183) + '\n' + config.get_localized_string(70181) % len(play_items))
|
|
|
|
# if config.get_setting("server_reorder", "downloads") == 1:
|
|
play_items.sort(key=sort_method)
|
|
|
|
# if progreso.iscanceled():
|
|
# return {"downloadStatus": STATUS_CODES.canceled}
|
|
finally:
|
|
progreso.close()
|
|
|
|
# We go through the list of servers, until we find one that works
|
|
for play_item in play_items:
|
|
play_item = item.clone(**play_item.__dict__)
|
|
play_item.contentAction = play_item.action
|
|
play_item.infoLabels = item.infoLabels
|
|
|
|
result = download_from_server(play_item)
|
|
|
|
# if progreso.iscanceled():
|
|
# result["downloadStatus"] = STATUS_CODES.canceled
|
|
|
|
# Whether the download is canceled or completed, we stop trying more options
|
|
if result["downloadStatus"] in [STATUS_CODES.canceled, STATUS_CODES.completed]:
|
|
result["downloadServer"] = {"url": play_item.url, "server": play_item.server}
|
|
break
|
|
|
|
return result
|
|
|
|
|
|
def select_server(item):
|
|
if item.server:
|
|
return "Auto"
|
|
info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url))
|
|
progreso = platformtools.dialog_progress_bg(config.get_localized_string(30101), config.get_localized_string(70179))
|
|
try:
|
|
if item.downloadItemlist:
|
|
info('using cached servers')
|
|
play_items = [Item().fromurl(i) for i in item.downloadItemlist]
|
|
else:
|
|
if item.contentChannel in ['community', 'videolibrary']:
|
|
channel = __import__('specials.%s' % item.contentChannel, None, None, ['specials.%s' % item.contentChannel])
|
|
else:
|
|
channel = __import__('channels.%s' % item.contentChannel, None, None, ['channels.%s' % item.contentChannel])
|
|
progreso.update(50, config.get_localized_string(70184) + '\n' + config.get_localized_string(70180) % item.contentChannel)
|
|
|
|
if hasattr(channel, item.contentAction):
|
|
play_items = getattr(channel, item.contentAction)(
|
|
item.clone(action=item.contentAction, channel=item.contentChannel))
|
|
else:
|
|
play_items = servertools.find_video_items(item.clone(action=item.contentAction, channel=item.contentChannel))
|
|
|
|
play_items = [x for x in play_items if x.action == "play" and not "trailer" in x.title.lower()]
|
|
progreso.update(100, config.get_localized_string(70183) + '\n' + config.get_localized_string(70181) % len(play_items))
|
|
finally:
|
|
progreso.close()
|
|
|
|
for x, i in enumerate(play_items):
|
|
if not i.server and hasattr(channel, "play"):
|
|
play_items[x] = getattr(channel, "play")(i)
|
|
|
|
if len(play_items) == 1:
|
|
# if there is only one server select it
|
|
seleccion = 1
|
|
else:
|
|
# otherwise it shows the selection window
|
|
seleccion = platformtools.serverWindow(item, [Item(title='Auto', thumbnail=get_thumb('downloads.png'), action='auto')] + play_items, False)
|
|
# seleccion = platformtools.dialog_select(config.get_localized_string(70192), ["Auto"] + [s.serverName for s in play_items])
|
|
|
|
if seleccion != -1: # not canceled
|
|
if seleccion.action != 'auto':
|
|
update_json(item.path, {
|
|
"downloadServer": {"url": seleccion.url, "server": seleccion.server}})
|
|
return seleccion
|
|
else:
|
|
update_json(item.path, {"downloadServer": {}})
|
|
return 'Auto'
|
|
# platformtools.itemlist_refresh()
|
|
|
|
|
|
def start_download(item):
|
|
info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url))
|
|
# We already have a server, we just need to download
|
|
if item.contentAction == "play":
|
|
ret = download_from_server(item)
|
|
elif item.downloadServer and item.downloadServer.get("server"):
|
|
ret = download_from_server(
|
|
item.clone(server=item.downloadServer.get("server"), url=item.downloadServer.get("url"),
|
|
contentAction="play"))
|
|
# We don't have a server, we need to find the best
|
|
else:
|
|
ret = download_from_best_server(item)
|
|
|
|
if ret["downloadStatus"] == STATUS_CODES.completed and config.get_setting("library_move"):
|
|
filetools.remove(item.path)
|
|
else:
|
|
update_json(item.path, ret)
|
|
return ret["downloadStatus"]
|
|
|
|
|
|
def get_episodes(item):
|
|
info("contentAction: %s | contentChannel: %s | contentType: %s" % (item.contentAction, item.contentChannel, item.contentType))
|
|
|
|
if 'dlseason' in item:
|
|
season = True
|
|
season_number = item.dlseason
|
|
else:
|
|
season = False
|
|
# The item we want to download NOW is an episode
|
|
if item.contentType == "episode":
|
|
episodes = [item.clone()]
|
|
|
|
# The item is a series or season
|
|
elif item.contentType in ["tvshow", "season"]:
|
|
if item.downloadItemlist:
|
|
episodes = [Item().fromurl(i) for i in item.downloadItemlist]
|
|
else:
|
|
# The item is a series or season...
|
|
if item.contentChannel in ['community', 'videolibrary']:
|
|
channel = __import__('specials.%s' % item.contentChannel, None, None, ["specials.%s" % item.contentChannel])
|
|
else:
|
|
channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel])
|
|
# We get the list of episodes
|
|
episodes = getattr(channel, item.contentAction)(item)
|
|
|
|
itemlist = []
|
|
if episodes and not scrapertools.find_single_match(episodes[0].title, r'(\d+.\d+)') and item.channel not in ['videolibrary'] and item.action != 'season':
|
|
from platformcode.autorenumber import select_type, renumber, check
|
|
# support.dbg()
|
|
if not check(item):
|
|
select_type(item)
|
|
return get_episodes(item)
|
|
else:
|
|
renumber(episodes, item)
|
|
|
|
# We get the list of episodes...
|
|
for episode in episodes:
|
|
# If we started from an item that was already an episode, this data is already good, it should not be modified
|
|
if item.contentType != "episode":
|
|
episode.contentAction = episode.action
|
|
episode.contentChannel = episode.channel
|
|
|
|
# If the result is a season, it is not worth it, we have to download the episodes of each season
|
|
if episode.contentType == "season":
|
|
itemlist.extend(get_episodes(episode))
|
|
|
|
# If the result is an episode is already what we need, we prepare it to add it to the download
|
|
if episode.contentType == "episode":
|
|
|
|
# We pass the id to the episode
|
|
if not episode.infoLabels["tmdb_id"]:
|
|
episode.infoLabels["tmdb_id"] = item.infoLabels["tmdb_id"]
|
|
|
|
# Episode, Season and Title
|
|
if not episode.contentSeason or not episode.contentEpisodeNumber:
|
|
season_and_episode = scrapertools.get_season_and_episode(episode.title)
|
|
if season_and_episode:
|
|
episode.contentSeason = season_and_episode.split("x")[0]
|
|
episode.contentEpisodeNumber = season_and_episode.split("x")[1]
|
|
|
|
# Episode, Season and Title...
|
|
if item.infoLabels["tmdb_id"]:
|
|
scraper.find_and_set_infoLabels(episode)
|
|
|
|
# Episode, Season and Title
|
|
if not episode.contentTitle:
|
|
episode.contentTitle = re.sub(r"\[[^\]]+\]|\([^\)]+\)|\d*x\d*\s*-", "", episode.title).strip()
|
|
|
|
episode.downloadFilename = filetools.validate_path(filetools.join(item.downloadFilename, "%dx%0.2d - %s" % (episode.contentSeason, episode.contentEpisodeNumber, episode.contentTitle.strip())))
|
|
if season:
|
|
if episode.contentSeason == int(season_number):
|
|
itemlist.append(episode)
|
|
else:
|
|
itemlist.append(episode)
|
|
|
|
|
|
# Any other result is not worth it, we ignore it
|
|
else:
|
|
info("Omitiendo item no válido:", episode.tostring())
|
|
|
|
# Any other result is not worth it, we ignore it...
|
|
itemlist = videolibrarytools.filter_list(itemlist)
|
|
|
|
return itemlist
|
|
|
|
|
|
def write_json(item):
|
|
info()
|
|
|
|
channel = item.from_channel if item.from_channel else item.channel
|
|
item.action = "menu"
|
|
item.channel = "downloads"
|
|
item.downloadStatus = STATUS_CODES.stoped
|
|
item.downloadProgress = 0
|
|
item.downloadSize = 0
|
|
item.downloadCompleted = 0
|
|
title = re.sub(r'(?:\[[^\]]+\]|%s[^-]+-\s*)' %config.get_localized_string(60356), '', item.title).strip()
|
|
if not item.contentThumbnail:
|
|
item.contentThumbnail = item.thumbnail
|
|
|
|
for name in ["text_bold", "text_color", "text_italic", "context", "totalItems", "viewmode", "title", "contentTitle", "thumbnail"]:
|
|
if name in item.__dict__:
|
|
item.__dict__.pop(name)
|
|
|
|
if item.contentType == 'episode':
|
|
naming = title + typo(item.infoLabels['IMDBNumber'], '_ []') + typo(channel, '_ []')
|
|
else:
|
|
naming = item.fulltitle + typo(item.infoLabels['IMDBNumber'], '_ []') + typo(channel, '_ []')
|
|
naming += typo(item.contentLanguage, '_ []') if item.contentLanguage else ''
|
|
naming += typo(item.quality, '_ []') if item.quality else ''
|
|
|
|
path = filetools.join(DOWNLOAD_LIST_PATH, naming + ".json")
|
|
if filetools.isfile(path):
|
|
filetools.remove(path)
|
|
|
|
item.path = path
|
|
filetools.write(path, item.tojson())
|
|
time.sleep(0.1)
|
|
|
|
|
|
def save_download(item):
|
|
show_disclaimer()
|
|
if item.channel != 'downloads':
|
|
item.from_channel = item.channel
|
|
item.from_action = item.action
|
|
|
|
item.channel = "downloads"
|
|
item.action = "save_download_background"
|
|
xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")")
|
|
|
|
|
|
def save_download_background(item):
|
|
info()
|
|
# Menu contextual
|
|
if item.from_action and item.from_channel:
|
|
item.channel = item.from_channel
|
|
item.action = item.from_action
|
|
del item.from_action
|
|
del item.from_channel
|
|
|
|
item.contentChannel = item.from_channel if item.from_channel else item.channel
|
|
item.contentAction = item.from_action if item.from_action else item.action
|
|
|
|
if item.channel == 'videolibrary':
|
|
from specials import videolibrary
|
|
|
|
if not item.parent:
|
|
parent = item
|
|
else:
|
|
parent = Item().fromurl(item.parent)
|
|
parent.contentChannel = 'videolibrary'
|
|
if item.downloadItemlist: # episode
|
|
parent.downloadItemlist = item.downloadItemlist
|
|
elif item.unseen: # unseen episodes
|
|
parent.downloadItemlist = [i.tourl() for i in videolibrary.get_episodes(parent) if i.action == 'findvideos' and parent.library_playcounts[scrapertools.get_season_and_episode(i.title)] == 0]
|
|
|
|
else: # tvshow or season
|
|
parent.downloadItemlist = [i.tourl() for i in videolibrary.get_episodes(parent) if i.action == 'findvideos']
|
|
if parent.contentType in ["tvshow", "episode", "season"]:
|
|
if not item.unseen and parent.contentSeason: # if no season, this is episode view, let's download entire serie
|
|
parent.dlseason = parent.contentSeason # this is season view, let's download season
|
|
save_download_tvshow(parent)
|
|
elif parent.contentType == "movie":
|
|
save_download_movie(parent)
|
|
else:
|
|
if item.contentType in ["tvshow", "episode", "season"]:
|
|
if ('download' in item and item.channel != 'community') or (item.channel == 'community' and config.get_setting('show_seasons',item.channel) == False):
|
|
heading = config.get_localized_string(70594) # <- Enter the season number
|
|
item.dlseason = platformtools.dialog_numeric(0, heading, '')
|
|
if item.dlseason:
|
|
save_download_tvshow(item)
|
|
else:
|
|
save_download_tvshow(item)
|
|
|
|
elif item.contentType == "movie":
|
|
save_download_movie(item)
|
|
else:
|
|
save_download_video(item)
|
|
|
|
|
|
def save_download_videolibrary(item):
|
|
info()
|
|
show_disclaimer()
|
|
item.contentChannel = 'videolibrary'
|
|
item.channel = "downloads"
|
|
item.action = "save_download_background"
|
|
xbmc.executebuiltin("RunPlugin(plugin://plugin.video.kod/?" + item.tourl() + ")")
|
|
|
|
|
|
def save_download_video(item):
|
|
info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle))
|
|
|
|
set_movie_title(item)
|
|
|
|
item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentTitle.strip(), item.contentChannel))
|
|
|
|
write_json(item)
|
|
|
|
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
|
|
platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle + '\n' + config.get_localized_string(30109))
|
|
else:
|
|
start_download(item)
|
|
|
|
|
|
def save_download_movie(item):
|
|
info("contentAction: %s | contentChannel: %s | contentTitle: %s" % ( item.contentAction, item.contentChannel, item.contentTitle))
|
|
|
|
progreso = platformtools.dialog_progress_bg(config.get_localized_string(30101), config.get_localized_string(70191))
|
|
|
|
set_movie_title(item)
|
|
|
|
result = scraper.find_and_set_infoLabels(item)
|
|
if not result:
|
|
progreso.close()
|
|
return save_download_video(item)
|
|
|
|
progreso.update(0, config.get_localized_string(60062))
|
|
|
|
item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentTitle.strip(), item.infoLabels['IMDBNumber']))
|
|
item.backupFilename = filetools.validate_path("%s [%s]" % (item.contentTitle.strip(), item.infoLabels['IMDBNumber']))
|
|
|
|
write_json(item)
|
|
|
|
progreso.close()
|
|
|
|
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
|
|
platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle + '\n' + config.get_localized_string(30109))
|
|
else:
|
|
# from core.support import dbg;dbg()
|
|
play_item = select_server(item)
|
|
if play_item:
|
|
if type(play_item) == str and play_item == 'Auto':
|
|
start_download(item)
|
|
else:
|
|
play_item = item.clone(**play_item.__dict__)
|
|
play_item.contentAction = play_item.action
|
|
play_item.infoLabels = item.infoLabels
|
|
start_download(play_item)
|
|
|
|
|
|
def save_download_tvshow(item):
|
|
info("contentAction: %s | contentChannel: %s | contentType: %s | contentSerieName: %s" % (item.contentAction, item.contentChannel, item.contentType, item.contentSerieName))
|
|
progreso = platformtools.dialog_progress_bg(config.get_localized_string(30101), config.get_localized_string(70188))
|
|
try:
|
|
item.show = item.fulltitle
|
|
if item.channel not in ['videolibrary']:
|
|
scraper.find_and_set_infoLabels(item)
|
|
|
|
if not item.contentSerieName: item.contentSerieName = item.fulltitle
|
|
|
|
if item.strm_path: item.downloadFilename = filetools.validate_path(item.strm_path.split(os.sep)[-2])
|
|
else: item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentSerieName, item.infoLabels['IMDBNumber']))
|
|
|
|
if config.get_setting("lowerize_title", "videolibrary"):
|
|
item.downloadFilename = item.downloadFilename.lower()
|
|
|
|
progreso.update(0, config.get_localized_string(70186) + '\n' + config.get_localized_string(70180) % item.contentChannel)
|
|
|
|
episodes = get_episodes(item)
|
|
|
|
progreso.update(0, config.get_localized_string(70190))
|
|
|
|
for x, i in enumerate(episodes):
|
|
progreso.update(old_div(x * 100, len(episodes)), "%dx%0.2d: %s" % (i.contentSeason, i.contentEpisodeNumber, i.contentTitle))
|
|
write_json(i)
|
|
finally:
|
|
progreso.close()
|
|
|
|
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
|
|
platformtools.dialog_ok(config.get_localized_string(30101), str(len(episodes)) + config.get_localized_string(30110) + '\n' + item.contentSerieName + '\n' + config.get_localized_string(30109))
|
|
|
|
else:
|
|
if len(episodes) == 1:
|
|
play_item = select_server(episodes[0])
|
|
if play_item: # not pressed cancel
|
|
if type(play_item) == str and play_item == 'Auto':
|
|
start_download(episodes[0])
|
|
else:
|
|
play_item = episodes[0].clone(**play_item.__dict__)
|
|
play_item.contentAction = play_item.action
|
|
play_item.infoLabels = episodes[0].infoLabels
|
|
start_download(play_item)
|
|
else:
|
|
for i in episodes:
|
|
i.contentChannel = item.contentChannel
|
|
res = start_download(i)
|
|
if res == STATUS_CODES.canceled:
|
|
break
|
|
|
|
|
|
def set_movie_title(item):
|
|
if not item.contentTitle:
|
|
item.contentTitle = re.sub(r"\[[^\]]+\]|\([^\)]+\)", "", item.contentTitle).strip()
|
|
|
|
if not item.contentTitle:
|
|
item.contentTitle = re.sub(r"\[[^\]]+\]|\([^\)]+\)", "", item.title).strip()
|
|
|
|
|
|
def show_disclaimer():
|
|
line1 = config.get_localized_string(70690)
|
|
line2 = config.get_localized_string(70691)
|
|
line3 = config.get_localized_string(70692)
|
|
platformtools.dialog_ok(config.get_localized_string(20000), line1 + '\n' + line2 + '\n' + line3)
|