mirror of
https://github.com/jellyfin/jellycon.git
synced 2024-11-23 22:19:54 +00:00
354 lines
13 KiB
Python
354 lines
13 KiB
Python
# coding=utf-8
|
|
# Gnu General Public License - see LICENSE.TXT
|
|
from __future__ import division, absolute_import, print_function, unicode_literals
|
|
|
|
from six.moves.urllib.parse import unquote
|
|
import requests
|
|
import base64
|
|
import sys
|
|
import threading
|
|
import time
|
|
|
|
import xbmcgui
|
|
import xbmcplugin
|
|
import xbmc
|
|
import xbmcaddon
|
|
|
|
from .jellyfin import api
|
|
from .lazylogger import LazyLogger
|
|
from .jsonrpc import JsonRpc, get_value
|
|
from .utils import translate_string, load_user_details
|
|
from .kodi_utils import HomeWindow
|
|
from .item_functions import get_art
|
|
|
|
log = LazyLogger(__name__)
|
|
|
|
|
|
class CacheArtwork(threading.Thread):
|
|
|
|
stop_all_activity = False
|
|
|
|
def __init__(self):
|
|
log.debug("CacheArtwork init")
|
|
self.stop_all_activity = False
|
|
super(CacheArtwork, self).__init__()
|
|
|
|
def stop_activity(self):
|
|
self.stop_all_activity = True
|
|
|
|
def run(self):
|
|
log.debug("CacheArtwork background thread started")
|
|
last_update = 0
|
|
home_window = HomeWindow()
|
|
settings = xbmcaddon.Addon()
|
|
latest_content_hash = "never"
|
|
check_interval = int(settings.getSetting('cacheImagesOnScreenSaver_interval'))
|
|
check_interval = check_interval * 60
|
|
monitor = xbmc.Monitor()
|
|
monitor.waitForAbort(5)
|
|
|
|
while not self.stop_all_activity and not monitor.abortRequested() and xbmc.getCondVisibility("System.ScreenSaverActive"):
|
|
content_hash = home_window.get_property("jellycon_widget_reload")
|
|
if (check_interval != 0 and (time.time() - last_update) > check_interval) or (latest_content_hash != content_hash):
|
|
log.debug("CacheArtwork background thread - triggered")
|
|
if monitor.waitForAbort(10):
|
|
break
|
|
if self.stop_all_activity or monitor.abortRequested():
|
|
break
|
|
self.cache_artwork_background()
|
|
last_update = time.time()
|
|
latest_content_hash = content_hash
|
|
|
|
monitor.waitForAbort(5)
|
|
|
|
log.debug("CacheArtwork background thread exited : stop_all_activity : {0}".format(self.stop_all_activity))
|
|
|
|
@staticmethod
|
|
def delete_cached_images(item_id):
|
|
log.debug("cache_delete_for_links")
|
|
|
|
progress = xbmcgui.DialogProgress()
|
|
progress.create(translate_string(30281))
|
|
progress.update(30, translate_string(30347))
|
|
|
|
item_image_url_part = "Items/%s/Images/" % item_id
|
|
item_image_url_part = item_image_url_part.replace("/", "%2f")
|
|
log.debug("texture ids: {0}".format(item_image_url_part))
|
|
|
|
# is the web server enabled
|
|
web_query = {"setting": "services.webserver"}
|
|
result = JsonRpc('Settings.GetSettingValue').execute(web_query)
|
|
xbmc_webserver_enabled = result['result']['value']
|
|
if not xbmc_webserver_enabled:
|
|
xbmcgui.Dialog().ok(translate_string(30294), translate_string(30295))
|
|
return
|
|
|
|
params = {"properties": ["url"]}
|
|
json_result = JsonRpc('Textures.GetTextures').execute(params)
|
|
textures = json_result.get("result", {}).get("textures", [])
|
|
log.debug("texture ids: {0}".format(textures))
|
|
|
|
progress.update(70, translate_string(30346))
|
|
|
|
delete_count = 0
|
|
for texture in textures:
|
|
texture_id = texture["textureid"]
|
|
texture_url = texture["url"]
|
|
if item_image_url_part in texture_url:
|
|
delete_count += 1
|
|
log.debug("removing texture id: {0}".format(texture_id))
|
|
params = {"textureid": int(texture_id)}
|
|
JsonRpc('Textures.RemoveTexture').execute(params)
|
|
|
|
del textures
|
|
|
|
progress.update(100, translate_string(30125))
|
|
progress.close()
|
|
|
|
xbmcgui.Dialog().ok(translate_string(30281), '{}: {}'.format(translate_string(30344), delete_count))
|
|
|
|
def cache_artwork_interactive(self):
|
|
log.debug("cache_artwork_interactive")
|
|
|
|
xbmcplugin.endOfDirectory(int(sys.argv[1]), cacheToDisc=False)
|
|
|
|
# is the web server enabled
|
|
web_query = {"setting": "services.webserver"}
|
|
result = JsonRpc('Settings.GetSettingValue').execute(web_query)
|
|
xbmc_webserver_enabled = result['result']['value']
|
|
if not xbmc_webserver_enabled:
|
|
xbmcgui.Dialog().ok(translate_string(30294), '{} - {}'.format(translate_string(30295), translate_string(30355)))
|
|
xbmc.executebuiltin('ActivateWindow(servicesettings)')
|
|
return
|
|
|
|
result_report = []
|
|
|
|
# ask questions
|
|
question_delete_unused = xbmcgui.Dialog().yesno(translate_string(30296), translate_string(30297))
|
|
question_cache_images = xbmcgui.Dialog().yesno(translate_string(30299), translate_string(30300))
|
|
|
|
delete_canceled = False
|
|
# now do work - delete unused
|
|
if question_delete_unused:
|
|
delete_pdialog = xbmcgui.DialogProgress()
|
|
delete_pdialog.create(translate_string(30298), "")
|
|
index = 0
|
|
|
|
params = {"properties": ["url"]}
|
|
json_result = JsonRpc('Textures.GetTextures').execute(params)
|
|
textures = json_result.get("result", {}).get("textures", [])
|
|
|
|
jellyfin_texture_urls = self.get_jellyfin_artwork(delete_pdialog)
|
|
|
|
log.debug("kodi textures: {0}".format(textures))
|
|
log.debug("jellyfin texture urls: {0}".format(jellyfin_texture_urls))
|
|
|
|
if jellyfin_texture_urls is not None:
|
|
|
|
unused_texture_ids = set()
|
|
for texture in textures:
|
|
url = texture.get("url")
|
|
url = unquote(url)
|
|
url = url.replace("image://", "")
|
|
url = url[0:-1]
|
|
if url.find("/") > -1 and url not in jellyfin_texture_urls or url.find("localhost:24276") > -1:
|
|
unused_texture_ids.add(texture["textureid"])
|
|
|
|
total = len(unused_texture_ids)
|
|
log.debug("unused texture ids: {0}".format(unused_texture_ids))
|
|
|
|
for texture_id in unused_texture_ids:
|
|
params = {"textureid": int(texture_id)}
|
|
JsonRpc('Textures.RemoveTexture').execute(params)
|
|
percentage = int((float(index) / float(total)) * 100)
|
|
message = "%s of %s" % (index, total)
|
|
delete_pdialog.update(percentage, message)
|
|
|
|
index += 1
|
|
if delete_pdialog.iscanceled():
|
|
delete_canceled = True
|
|
break
|
|
|
|
result_report.append(translate_string(30385) + str(len(textures)))
|
|
result_report.append(translate_string(30386) + str(len(unused_texture_ids)))
|
|
result_report.append(translate_string(30387) + str(index))
|
|
|
|
del textures
|
|
del jellyfin_texture_urls
|
|
del unused_texture_ids
|
|
delete_pdialog.close()
|
|
del delete_pdialog
|
|
|
|
if delete_canceled:
|
|
xbmc.sleep(2000)
|
|
|
|
# now do work - cache images
|
|
if question_cache_images:
|
|
cache_pdialog = xbmcgui.DialogProgress()
|
|
cache_pdialog.create(translate_string(30301), "")
|
|
cache_report = self.cache_artwork(cache_pdialog)
|
|
cache_pdialog.close()
|
|
del cache_pdialog
|
|
if cache_report:
|
|
result_report.extend(cache_report)
|
|
|
|
if len(result_report) > 0:
|
|
msg = "\r\n".join(result_report)
|
|
xbmcgui.Dialog().textviewer(translate_string(30125), msg, usemono=True)
|
|
|
|
def cache_artwork_background(self):
|
|
log.debug("cache_artwork_background")
|
|
dp = xbmcgui.DialogProgressBG()
|
|
dp.create(translate_string(30301), "")
|
|
result_text = None
|
|
try:
|
|
result_text = self.cache_artwork(dp)
|
|
except Exception as err:
|
|
log.error("Cache Images Failed : {0}".format(err))
|
|
dp.close()
|
|
del dp
|
|
if result_text is not None:
|
|
log.debug("Cache Images reuslt : {0}".format(" - ".join(result_text)))
|
|
|
|
def get_jellyfin_artwork(self, progress):
|
|
log.debug("get_jellyfin_artwork")
|
|
user_details = load_user_details()
|
|
user_id = user_details.get('user_id')
|
|
|
|
url = ""
|
|
url += "/Users/{}/Items".format(user_id)
|
|
url += "?Recursive=true"
|
|
url += "&EnableUserData=False"
|
|
url += "&Fields=BasicSyncInfo"
|
|
url += "&IncludeItemTypes=Movie,Series,Episode,BoxSet"
|
|
url += "&ImageTypeLimit=1"
|
|
url += "&format=json"
|
|
|
|
results = api.get(url)
|
|
if results is None:
|
|
results = []
|
|
|
|
if isinstance(results, dict):
|
|
results = results.get("Items")
|
|
|
|
settings = xbmcaddon.Addon()
|
|
server = settings.getSetting('server_address')
|
|
log.debug("Jellyfin Item Count Count: {0}".format(len(results)))
|
|
|
|
if self.stop_all_activity:
|
|
return None
|
|
|
|
progress.update(0, translate_string(30359))
|
|
|
|
texture_urls = set()
|
|
|
|
for item in results:
|
|
art = get_art(item, server)
|
|
for art_type in art:
|
|
texture_urls.add(art[art_type])
|
|
|
|
return texture_urls
|
|
|
|
def cache_artwork(self, progress):
|
|
log.debug("cache_artwork")
|
|
|
|
# is the web server enabled
|
|
if not get_value("services.webserver"):
|
|
log.error("Kodi web server not enabled, can not cache images")
|
|
return
|
|
|
|
# get the port
|
|
xbmc_port = get_value("services.webserverport")
|
|
log.debug("xbmc_port: {0}".format(xbmc_port))
|
|
|
|
# get the user
|
|
xbmc_username = get_value("services.webserverusername")
|
|
log.debug("xbmc_username: {0}".format(xbmc_username))
|
|
|
|
# get the password
|
|
xbmc_password = get_value("services.webserverpassword")
|
|
|
|
progress.update(0, translate_string(30356))
|
|
|
|
params = {"properties": ["url"]}
|
|
json_result = JsonRpc('Textures.GetTextures').execute(params)
|
|
textures = json_result.get("result", {}).get("textures", [])
|
|
log.debug("Textures.GetTextures Count: {0}".format(len(textures)))
|
|
|
|
if self.stop_all_activity:
|
|
return
|
|
|
|
progress.update(0, translate_string(30357))
|
|
|
|
texture_urls = set()
|
|
for texture in textures:
|
|
url = texture.get("url")
|
|
url = unquote(url)
|
|
url = url.replace("image://", "")
|
|
url = url[0:-1]
|
|
texture_urls.add(url)
|
|
|
|
del textures
|
|
del json_result
|
|
|
|
log.debug("texture_urls Count: {0}".format(len(texture_urls)))
|
|
|
|
if self.stop_all_activity:
|
|
return
|
|
|
|
progress.update(0, translate_string(30358))
|
|
|
|
jellyfin_texture_urls = self.get_jellyfin_artwork(progress)
|
|
if jellyfin_texture_urls is None:
|
|
return
|
|
|
|
missing_texture_urls = set()
|
|
|
|
for image_url in jellyfin_texture_urls:
|
|
if image_url not in texture_urls and not image_url.endswith("&Tag=") and len(image_url) > 0:
|
|
missing_texture_urls.add(image_url)
|
|
|
|
if self.stop_all_activity:
|
|
return
|
|
|
|
log.debug("texture_urls: {0}".format(texture_urls))
|
|
log.debug("missing_texture_urls: {0}".format(missing_texture_urls))
|
|
log.debug("Number of existing textures: {0}".format(len(texture_urls)))
|
|
log.debug("Number of missing textures: {0}".format(len(missing_texture_urls)))
|
|
|
|
kodi_http_server = "localhost:" + str(xbmc_port)
|
|
headers = {}
|
|
if xbmc_password:
|
|
auth = "%s:%s" % (xbmc_username, xbmc_password)
|
|
headers = {'Authorization': 'Basic %s' % base64.b64encode(auth)}
|
|
|
|
total = len(missing_texture_urls)
|
|
|
|
count_done = 0
|
|
for index, get_url in enumerate(missing_texture_urls, 1):
|
|
kodi_texture_url = "/image/image://{0}".format(get_url)
|
|
log.debug("kodi_texture_url: {0}".format(kodi_texture_url))
|
|
|
|
percentage = int((float(index) / float(total)) * 100)
|
|
message = "%s of %s" % (index, total)
|
|
progress.update(percentage, message)
|
|
|
|
cache_url = "http://%s%s" % (kodi_http_server, kodi_texture_url)
|
|
data = requests.get(cache_url, timeout=20, headers=headers)
|
|
|
|
if data.status_code == 200:
|
|
count_done += 1
|
|
log.debug("Get Image Result: {0}".format(data.status_code))
|
|
|
|
if isinstance(progress, xbmcgui.DialogProgress) and progress.iscanceled():
|
|
break
|
|
|
|
if self.stop_all_activity:
|
|
break
|
|
|
|
result_report = []
|
|
result_report.append(translate_string(30302) + str(len(texture_urls)))
|
|
result_report.append(translate_string(30303) + str(len(missing_texture_urls)))
|
|
result_report.append(translate_string(30304) + str(count_done))
|
|
return result_report
|