Files
jellycon/resources/lib/functions.py

1033 lines
36 KiB
Python
Raw Normal View History

# Gnu General Public License - see LICENSE.TXT
from __future__ import division, absolute_import, print_function, unicode_literals
from six.moves.urllib.parse import quote, unquote, parse_qsl
import sys
import os
import time
import cProfile
import pstats
import json
2021-01-02 09:52:37 -05:00
from six import StringIO
import xbmcplugin
import xbmcgui
import xbmcaddon
import xbmc
2019-06-02 12:20:54 +10:00
from .downloadutils import DownloadUtils, load_user_details
2020-06-21 11:27:09 +10:00
from .utils import get_art, send_event_notification, convert_size
2018-09-26 08:41:23 +10:00
from .kodi_utils import HomeWindow
from .clientinfo import ClientInformation
2019-03-03 10:43:56 +11:00
from .datamanager import DataManager, clear_cached_server_data
2020-06-26 14:46:57 +10:00
from .server_detect import check_server, check_connection_speed
from .loghandler import LazyLogger
from .menu_functions import display_main_menu, display_menu, show_movie_alpha_list, show_tvshow_alpha_list, show_genre_list, show_search, show_movie_pages
2018-10-26 14:04:54 +11:00
from .translation import string_load
2020-06-21 11:27:09 +10:00
from .server_sessions import show_server_sessions
2018-09-26 08:41:23 +10:00
from .action_menu import ActionMenu
2020-06-24 20:31:47 +10:00
from .bitrate_dialog import BitrateDialog
2020-04-14 13:24:01 +10:00
from .safe_delete_dialog import SafeDeleteDialog
2020-06-21 11:27:09 +10:00
from .widgets import get_widget_content, get_widget_content_cast, check_for_new_content
2019-01-11 10:24:42 +11:00
from . import trakttokodi
2018-09-26 08:41:23 +10:00
from .cache_images import CacheArtwork
2020-06-21 11:27:09 +10:00
from .dir_functions import get_content, process_directory
2019-10-14 11:55:18 +11:00
from .tracking import timer
2020-01-03 10:00:19 +11:00
from .skin_cloner import clone_default_skin
from .play_utils import play_file
__addon__ = xbmcaddon.Addon()
__addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
__cwd__ = __addon__.getAddonInfo('path')
PLUGINPATH = xbmc.translatePath(os.path.join(__cwd__))
log = LazyLogger(__name__)
kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2])
downloadUtils = DownloadUtils()
dataManager = DataManager()
2019-10-14 11:55:18 +11:00
@timer
2020-06-21 11:27:09 +10:00
def main_entry_point():
log.debug("===== JellyCon START =====")
settings = xbmcaddon.Addon()
2019-10-19 20:32:57 +11:00
profile_count = int(settings.getSetting('profile_count'))
pr = None
2019-10-19 20:32:57 +11:00
if profile_count > 0:
profile_count = profile_count - 1
settings.setSetting('profile_count', str(profile_count))
pr = cProfile.Profile()
pr.enable()
log.debug("Running Python: {0}".format(sys.version_info))
log.debug("Running JellyCon: {0}".format(ClientInformation().get_version()))
log.debug("Kodi BuildVersion: {0}".format(xbmc.getInfoLabel("System.BuildVersion")))
log.debug("Kodi Version: {0}".format(kodi_version))
log.debug("Script argument data: {0}".format(sys.argv))
2019-12-30 09:16:57 +11:00
params = get_params()
log.info("Script params: {0}".format(params))
2019-12-30 09:16:57 +11:00
request_path = params.get("request_path", None)
param_url = params.get('url', None)
if param_url:
param_url = unquote(param_url)
mode = params.get("mode", None)
2019-12-30 09:16:57 +11:00
if len(params) == 1 and request_path and request_path.find("/library/movies") > -1:
2020-06-21 11:27:09 +10:00
check_server()
2019-12-30 09:16:57 +11:00
new_params = {}
new_params["item_type"] = "Movie"
new_params["media_type"] = "movies"
2020-06-21 11:27:09 +10:00
show_content(new_params)
2019-12-30 09:16:57 +11:00
elif mode == "CHANGE_USER":
2020-06-21 11:27:09 +10:00
check_server(change_user=True, notify=False)
elif mode == "CACHE_ARTWORK":
CacheArtwork().cache_artwork_interactive()
elif mode == "DETECT_SERVER":
2020-06-21 11:27:09 +10:00
check_server(force=True, notify=True)
2017-05-20 11:20:54 +10:00
elif mode == "DETECT_SERVER_USER":
2020-06-21 11:27:09 +10:00
check_server(force=True, change_user=True, notify=False)
2020-06-26 14:46:57 +10:00
elif mode == "DETECT_CONNECTION_SPEED":
check_connection_speed()
elif mode == "playTrailer":
item_id = params["id"]
2020-06-21 11:27:09 +10:00
play_item_trailer(item_id)
elif mode == "MOVIE_ALPHA":
2019-11-07 16:05:29 +11:00
show_movie_alpha_list(params)
2019-02-09 10:17:43 +11:00
elif mode == "TVSHOW_ALPHA":
2019-11-07 16:05:29 +11:00
show_tvshow_alpha_list(params)
elif mode == "GENRES":
2019-11-07 16:05:29 +11:00
show_genre_list(params)
elif mode == "MOVIE_PAGES":
2019-11-07 16:05:29 +11:00
show_movie_pages(params)
2018-07-15 11:06:28 +10:00
elif mode == "TOGGLE_WATCHED":
toggle_watched(params)
2017-08-19 11:08:15 +10:00
elif mode == "SHOW_MENU":
show_menu(params)
2020-01-03 10:00:19 +11:00
elif mode == "CLONE_SKIN":
clone_default_skin()
elif mode == "SHOW_SETTINGS":
__addon__.openSettings()
2020-06-21 11:27:09 +10:00
window = xbmcgui.getCurrentWindowId()
if window == 10000:
2017-07-08 10:34:30 +10:00
log.debug("Currently in home - refreshing to allow new settings to be taken")
xbmc.executebuiltin("ActivateWindow(Home)")
2019-03-03 10:43:56 +11:00
elif mode == "CLEAR_CACHE":
clear_cached_server_data()
elif mode == "WIDGET_CONTENT":
2020-06-21 11:27:09 +10:00
get_widget_content(int(sys.argv[1]), params)
elif mode == "WIDGET_CONTENT_CAST":
get_widget_content_cast(int(sys.argv[1]), params)
2017-03-11 21:07:08 +11:00
elif mode == "SHOW_CONTENT":
2020-06-21 11:27:09 +10:00
check_server()
show_content(params)
elif mode == "SEARCH":
xbmcplugin.setContent(int(sys.argv[1]), 'files')
2018-07-11 12:22:41 +10:00
show_search()
elif mode == "NEW_SEARCH":
2018-07-11 12:22:41 +10:00
search_results(params)
elif mode == "NEW_SEARCH_PERSON":
search_results_person(params)
elif mode == "SHOW_SERVER_SESSIONS":
2020-06-21 11:27:09 +10:00
show_server_sessions()
elif mode == "TRAKTTOKODI":
trakttokodi.entry_point(params)
2019-11-06 07:14:33 +11:00
elif mode == "SHOW_ADDON_MENU":
display_menu(params)
elif mode == "GET_CONTENT_BY_TV_SHOW":
parent_id = __get_parent_id_from(params)
if parent_id is not None:
enriched_url = param_url + "&ParentId=" + parent_id
2020-06-21 11:27:09 +10:00
get_content(enriched_url, params)
else:
log.info("Unable to find TV show parent ID.")
else:
log.debug("JellyCon -> Mode: {0}".format(mode))
log.debug("JellyCon -> URL: {0}".format(param_url))
if mode == "GET_CONTENT":
2020-06-21 11:27:09 +10:00
get_content(param_url, params)
2017-04-13 06:58:25 +10:00
elif mode == "PLAY":
2020-06-21 11:27:09 +10:00
play_action(params)
else:
2020-06-21 11:27:09 +10:00
check_server()
2019-11-06 07:14:33 +11:00
display_main_menu()
2019-10-19 20:32:57 +11:00
if pr:
pr.disable()
2020-06-21 11:27:09 +10:00
file_time_stamp = time.strftime("%Y%m%d-%H%M%S")
tab_file_name = __addondir__ + "profile(" + file_time_stamp + ").txt"
s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s)
ps = ps.sort_stats('cumulative')
ps.print_stats()
ps.strip_dirs()
ps = ps.sort_stats('tottime')
ps.print_stats()
2020-06-21 11:27:09 +10:00
with open(tab_file_name, 'wb') as f:
2017-07-15 23:53:36 +10:00
f.write(s.getvalue())
log.debug("===== JellyCon FINISHED =====")
def __enrich_url(param_url, params):
enriched_url = param_url
parent_id = __get_parent_id_from(params)
if parent_id is not None:
enriched_url = param_url + "&ParentId=" + parent_id
return enriched_url
def __get_parent_id_from(params):
result = None
show_provider_ids = params.get("show_ids")
if show_provider_ids is not None:
log.debug("TV show providers IDs: {}".format(show_provider_ids))
get_show_url = "{server}/Users/{userid}/Items?fields=MediaStreams&Recursive=true" \
"&IncludeItemTypes=series&IncludeMedia=true&ImageTypeLimit=1&Limit=16" \
"&AnyProviderIdEquals=" + show_provider_ids
2020-06-21 11:27:09 +10:00
content = dataManager.get_content(get_show_url)
show = content.get("Items")
if len(show) == 1:
result = content.get("Items")[0].get("Id")
else:
log.debug("TV show not found for ids: {}".format(show_provider_ids))
else:
log.error("TV show parameter not found in request.")
return result
2018-07-15 11:06:28 +10:00
def toggle_watched(params):
log.debug("toggle_watched: {0}".format(params))
2018-07-15 11:06:28 +10:00
item_id = params.get("item_id", None)
if item_id is None:
return
url = "{server}/Users/{userid}/Items/" + item_id + "?format=json"
2018-07-15 11:06:28 +10:00
data_manager = DataManager()
2020-06-21 11:27:09 +10:00
result = data_manager.get_content(url)
log.debug("toggle_watched item info: {0}".format(result))
2018-07-15 11:06:28 +10:00
user_data = result.get("UserData", None)
if user_data is None:
return
if user_data.get("Played", False) is False:
2020-06-21 11:27:09 +10:00
mark_item_watched(item_id)
2018-07-15 11:06:28 +10:00
else:
2020-06-21 11:27:09 +10:00
mark_item_unwatched(item_id)
2018-07-15 11:06:28 +10:00
2020-06-21 11:27:09 +10:00
def mark_item_watched(item_id):
log.debug("Mark Item Watched: {0}".format(item_id))
url = "{server}/Users/{userid}/PlayedItems/" + item_id
2020-06-21 11:27:09 +10:00
downloadUtils.download_url(url, post_body="", method="POST")
check_for_new_content()
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2018-11-21 13:23:42 +11:00
if last_url:
log.debug("markWatched_lastUrl: {0}".format(last_url))
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2018-11-21 13:23:42 +11:00
xbmc.executebuiltin("Container.Refresh")
2020-06-21 11:27:09 +10:00
def mark_item_unwatched(item_id):
log.debug("Mark Item UnWatched: {0}".format(item_id))
url = "{server}/Users/{userid}/PlayedItems/" + item_id
2020-06-21 11:27:09 +10:00
downloadUtils.download_url(url, method="DELETE")
check_for_new_content()
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2018-11-21 13:23:42 +11:00
if last_url:
log.debug("markUnwatched_lastUrl: {0}".format(last_url))
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2018-11-21 13:23:42 +11:00
xbmc.executebuiltin("Container.Refresh")
2020-06-21 11:27:09 +10:00
def mark_item_favorite(item_id):
log.debug("Add item to favourites: {0}".format(item_id))
url = "{server}/Users/{userid}/FavoriteItems/" + item_id
2020-06-21 11:27:09 +10:00
downloadUtils.download_url(url, post_body="", method="POST")
check_for_new_content()
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2018-11-21 13:23:42 +11:00
if last_url:
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2018-11-21 13:23:42 +11:00
xbmc.executebuiltin("Container.Refresh")
2020-06-21 11:27:09 +10:00
def unmark_item_favorite(item_id):
log.debug("Remove item from favourites: {0}".format(item_id))
url = "{server}/Users/{userid}/FavoriteItems/" + item_id
2020-06-21 11:27:09 +10:00
downloadUtils.download_url(url, method="DELETE")
check_for_new_content()
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2018-11-21 13:23:42 +11:00
if last_url:
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2018-11-21 13:23:42 +11:00
xbmc.executebuiltin("Container.Refresh")
2020-03-28 17:58:29 +11:00
def delete(item_id):
item = downloadUtils.download_url("{server}/Users/{userid}/Items/" + item_id + "?format=json")
2018-03-05 15:43:12 +11:00
item_id = item.get("Id")
2020-03-28 17:58:29 +11:00
item_name = item.get("Name", "")
series_name = item.get("SeriesName", "")
ep_number = item.get("IndexNumber", -1)
final_name = ""
2018-03-05 15:43:12 +11:00
if series_name:
2020-03-28 17:58:29 +11:00
final_name += series_name + " - "
if ep_number != -1:
final_name += "Episode %02d - " % (ep_number,)
final_name += item_name
if not item.get("CanDelete", False):
xbmcgui.Dialog().ok(string_load(30135), string_load(30417), final_name)
return
2018-03-05 15:43:12 +11:00
2021-02-28 19:29:55 -05:00
return_value = xbmcgui.Dialog().yesno(string_load(30091), '{}\n{}'.format(final_name, string_load(30092)))
if return_value:
log.debug('Deleting Item: {0}'.format(item_id))
url = '{server}/Items/' + item_id
progress = xbmcgui.DialogProgress()
2018-10-26 14:04:54 +11:00
progress.create(string_load(30052), string_load(30053))
2020-06-21 11:27:09 +10:00
downloadUtils.download_url(url, method="DELETE")
progress.close()
2020-06-21 11:27:09 +10:00
check_for_new_content()
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2018-11-21 13:23:42 +11:00
if last_url:
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2018-11-21 13:23:42 +11:00
xbmc.executebuiltin("Container.Refresh")
2019-12-30 09:16:57 +11:00
def get_params():
'''
Retrieve the request data from Kodi
'''
2019-12-30 09:16:57 +11:00
plugin_path = sys.argv[0]
paramstring = sys.argv[2]
log.debug("Parameter string: {0}".format(paramstring))
log.debug("Plugin Path string: {0}".format(plugin_path))
2019-12-30 09:16:57 +11:00
param = dict(parse_qsl(paramstring[1:]))
2019-12-30 09:16:57 +11:00
2020-06-21 11:27:09 +10:00
# add plugin path
request_path = plugin_path.replace("plugin://plugin.video.jellycon", "")
2019-12-30 09:16:57 +11:00
param["request_path"] = request_path
log.debug("JellyCon -> Detected parameters: {0}".format(param))
return param
def show_menu(params):
log.debug("showMenu(): {0}".format(params))
2017-08-19 11:08:15 +10:00
2020-04-14 13:24:01 +10:00
home_window = HomeWindow()
2020-01-02 14:05:12 +11:00
settings = xbmcaddon.Addon()
item_id = params["item_id"]
url = "{server}/Users/{userid}/Items/" + item_id + "?format=json"
data_manager = DataManager()
2020-06-21 11:27:09 +10:00
result = data_manager.get_content(url)
log.debug("Menu item info: {0}".format(result))
if result is None:
return
2017-08-19 11:08:15 +10:00
action_items = []
2018-12-09 13:42:01 +11:00
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio", "TvChannel", "Program"]:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30314))
li.setProperty('menu_id', 'play')
action_items.append(li)
if result["Type"] in ["Season", "MusicAlbum", "Playlist"]:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30317))
li.setProperty('menu_id', 'play_all')
action_items.append(li)
2018-12-09 13:42:01 +11:00
if result["Type"] in ["Episode", "Movie", "Video", "TvChannel", "Program"]:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30275))
li.setProperty('menu_id', 'transcode')
action_items.append(li)
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio"]:
li = xbmcgui.ListItem(string_load(30402))
li.setProperty('menu_id', 'add_to_playlist')
action_items.append(li)
2019-02-10 17:10:19 +11:00
if result["Type"] in ("Movie", "Series"):
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30307))
li.setProperty('menu_id', 'play_trailer')
action_items.append(li)
if result["Type"] == "Episode" and result["ParentId"] is not None:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30327))
li.setProperty('menu_id', 'view_season')
action_items.append(li)
2019-06-02 20:09:18 +10:00
if result["Type"] in ("Series", "Season", "Episode"):
2018-12-03 09:01:27 +11:00
li = xbmcgui.ListItem(string_load(30354))
li.setProperty('menu_id', 'view_series')
action_items.append(li)
2020-04-14 19:31:55 +10:00
if result["Type"] == "Movie":
li = xbmcgui.ListItem("Show Extras")
li.setProperty('menu_id', 'show_extras')
action_items.append(li)
user_data = result.get("UserData", None)
if user_data:
progress = user_data.get("PlaybackPositionTicks", 0) != 0
played = user_data.get("Played", False)
if not played or progress:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30270))
li.setProperty('menu_id', 'mark_watched')
action_items.append(li)
if played or progress:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30271))
li.setProperty('menu_id', 'mark_unwatched')
action_items.append(li)
2020-06-21 11:27:09 +10:00
if user_data.get("IsFavorite", False) is False:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30272))
li.setProperty('menu_id', 'jellyfin_set_favorite')
action_items.append(li)
else:
2018-10-26 14:04:54 +11:00
li = xbmcgui.ListItem(string_load(30273))
li.setProperty('menu_id', 'jellyfin_unset_favorite')
action_items.append(li)
can_delete = result.get("CanDelete", False)
if can_delete:
li = xbmcgui.ListItem(string_load(30274))
li.setProperty('menu_id', 'delete')
action_items.append(li)
2017-08-19 11:08:15 +10:00
2020-06-21 11:27:09 +10:00
safe_delete = home_window.get_property("safe_delete_plugin_available") == "true"
2020-04-14 13:24:01 +10:00
if safe_delete:
li = xbmcgui.ListItem("Safe Delete")
li.setProperty('menu_id', 'safe_delete')
action_items.append(li)
2019-06-10 10:01:35 +10:00
li = xbmcgui.ListItem(string_load(30398))
2019-06-08 16:48:46 +10:00
li.setProperty('menu_id', 'refresh_server')
action_items.append(li)
2018-10-29 05:43:51 +11:00
li = xbmcgui.ListItem(string_load(30281))
li.setProperty('menu_id', 'refresh_images')
action_items.append(li)
2020-03-28 17:58:29 +11:00
if result["Type"] in ["Movie", "Series"]:
2020-06-21 11:27:09 +10:00
li = xbmcgui.ListItem(string_load(30399))
li.setProperty('menu_id', 'hide')
action_items.append(li)
2019-06-02 12:20:54 +10:00
2019-08-25 08:44:25 +10:00
li = xbmcgui.ListItem(string_load(30401))
li.setProperty('menu_id', 'info')
action_items.append(li)
2020-01-02 14:05:12 +11:00
window = xbmcgui.Window(xbmcgui.getCurrentWindowId())
2020-02-06 19:14:54 +11:00
container_view_id = str(window.getFocusId())
2020-01-02 14:05:12 +11:00
container_content_type = xbmc.getInfoLabel("Container.Content")
2020-02-06 19:14:54 +11:00
view_key = "view-" + container_content_type
current_default_view = settings.getSetting(view_key)
view_match = container_view_id == current_default_view
log.debug("View ID:{0} Content type:{1}".format(container_view_id, container_content_type))
2020-01-02 14:05:12 +11:00
if container_content_type in ["movies", "tvshows", "seasons", "episodes", "sets"]:
2020-02-06 19:14:54 +11:00
if view_match:
2020-08-16 23:51:56 +02:00
li = xbmcgui.ListItem("Unset as default view")
2020-02-06 19:14:54 +11:00
li.setProperty('menu_id', 'unset_view')
action_items.append(li)
else:
2020-08-16 23:51:56 +02:00
li = xbmcgui.ListItem("Set as default view")
2020-02-06 19:14:54 +11:00
li.setProperty('menu_id', 'set_view')
action_items.append(li)
2020-01-02 14:05:12 +11:00
2017-08-19 11:08:15 +10:00
action_menu = ActionMenu("ActionMenu.xml", PLUGINPATH, "default", "720p")
action_menu.setActionItems(action_items)
action_menu.doModal()
selected_action_item = action_menu.getActionItem()
selected_action = ""
if selected_action_item is not None:
selected_action = selected_action_item.getProperty('menu_id')
log.debug("Menu Action Selected: {0}".format(selected_action))
2017-08-19 11:08:15 +10:00
del action_menu
if selected_action == "play":
log.debug("Play Item")
2020-06-21 11:27:09 +10:00
play_action(params)
2020-01-02 14:05:12 +11:00
elif selected_action == "set_view":
log.debug("Settign view type for {0} to {1}".format(view_key, container_view_id))
2020-02-06 19:14:54 +11:00
settings.setSetting(view_key, container_view_id)
elif selected_action == "unset_view":
log.debug("Un-Settign view type for {0} to {1}".format(view_key, container_view_id))
2020-02-06 19:14:54 +11:00
settings.setSetting(view_key, "")
2020-01-02 14:05:12 +11:00
2019-06-08 16:48:46 +10:00
elif selected_action == "refresh_server":
url = ("{server}/Items/" + item_id + "/Refresh" +
2019-06-08 16:48:46 +10:00
"?Recursive=true" +
"&ImageRefreshMode=FullRefresh" +
"&MetadataRefreshMode=FullRefresh" +
"&ReplaceAllImages=true" +
"&ReplaceAllMetadata=true")
2020-06-21 11:27:09 +10:00
res = downloadUtils.download_url(url, post_body="", method="POST")
log.debug("Refresh Server Responce: {0}".format(res))
2019-06-08 16:48:46 +10:00
2019-06-02 12:20:54 +10:00
elif selected_action == "hide":
user_details = load_user_details(settings)
user_name = user_details["username"]
hide_tag_string = "hide-" + user_name
url = "{server}/Items/" + item_id + "/Tags/Add"
2019-06-02 12:20:54 +10:00
post_tag_data = {"Tags": [{"Name": hide_tag_string}]}
2020-06-21 11:27:09 +10:00
res = downloadUtils.download_url(url, post_body=post_tag_data, method="POST")
log.debug("Add Tag Responce: {0}".format(res))
2019-06-02 12:20:54 +10:00
2020-06-21 11:27:09 +10:00
check_for_new_content()
2019-06-02 12:20:54 +10:00
2020-06-21 11:27:09 +10:00
last_url = home_window.get_property("last_content_url")
2019-06-02 12:20:54 +10:00
if last_url:
log.debug("markUnwatched_lastUrl: {0}".format(last_url))
2020-06-21 11:27:09 +10:00
home_window.set_property("skip_cache_for_" + last_url, "true")
2019-06-02 12:20:54 +10:00
xbmc.executebuiltin("Container.Refresh")
elif selected_action == "play_all":
2020-06-21 11:27:09 +10:00
play_action(params)
elif selected_action == "play_trailer":
2020-06-21 11:27:09 +10:00
play_item_trailer(item_id)
2017-08-19 11:08:15 +10:00
elif selected_action == "transcode":
params['force_transcode'] = 'true'
2020-06-24 20:31:47 +10:00
force_max_stream_bitrate = settings.getSetting("force_max_stream_bitrate")
initial_bitrate_value = int(force_max_stream_bitrate)
bitrate_dialog = BitrateDialog("BitrateDialog.xml", PLUGINPATH, "default", "720p")
bitrate_dialog.initial_bitrate_value = initial_bitrate_value
bitrate_dialog.doModal()
selected_transcode_value = bitrate_dialog.selected_transcode_value
del bitrate_dialog
log.debug("selected_transcode_value: {0}".format(selected_transcode_value))
2020-06-24 20:31:47 +10:00
if selected_transcode_value > 0:
settings.setSetting("force_max_stream_bitrate", str(selected_transcode_value))
2020-06-26 14:46:57 +10:00
play_action(params)
elif selected_action == "add_to_playlist":
params["action"] = "add_to_playlist"
2020-06-21 11:27:09 +10:00
play_action(params)
elif selected_action == "jellyfin_set_favorite":
2020-06-21 11:27:09 +10:00
mark_item_favorite(item_id)
elif selected_action == "jellyfin_unset_favorite":
2020-06-21 11:27:09 +10:00
unmark_item_favorite(item_id)
2017-08-19 11:08:15 +10:00
elif selected_action == "mark_watched":
2020-06-21 11:27:09 +10:00
mark_item_watched(item_id)
2017-08-19 11:08:15 +10:00
elif selected_action == "mark_unwatched":
2020-06-21 11:27:09 +10:00
mark_item_unwatched(item_id)
2017-08-19 11:08:15 +10:00
elif selected_action == "delete":
2020-03-28 17:58:29 +11:00
delete(item_id)
2020-04-14 13:24:01 +10:00
elif selected_action == "safe_delete":
url = "{server}/jellyfin_safe_delete/delete_item/" + item_id
result = downloadUtils.download_url(url)
2020-04-14 13:24:01 +10:00
dialog = xbmcgui.Dialog()
if result:
log.debug("Safe_Delete_Action: {0}".format(result))
2020-04-14 13:24:01 +10:00
action_token = result["action_token"]
2020-04-16 22:07:03 +10:00
message = "You are about to delete the following item[CR][CR]"
message += "Type: " + result["item_info"]["Item_type"] + "[CR]"
if result["item_info"]["Item_type"] == "Series":
message += "Name: " + result["item_info"]["item_name"] + "[CR]"
elif result["item_info"]["Item_type"] == "Season":
message += "Season: " + str(result["item_info"]["season_number"]) + "[CR]"
message += "Name: " + result["item_info"]["season_name"] + "[CR]"
elif result["item_info"]["Item_type"] == "Episode":
message += "Series: " + result["item_info"]["series_name"] + "[CR]"
message += "Season: " + result["item_info"]["season_name"] + "[CR]"
message += "Episode: " + str(result["item_info"]["episode_number"]) + "[CR]"
message += "Name: " + result["item_info"]["item_name"] + "[CR]"
else:
message += "Name: " + result["item_info"]["item_name"] + "[CR]"
message += "[CR]File List[CR][CR]"
2020-04-14 13:24:01 +10:00
for file_info in result["file_list"]:
2020-04-18 11:05:51 +10:00
message += " - " + file_info["Key"] + " (" + convert_size(file_info["Value"]) + ")[CR]"
2020-04-14 13:24:01 +10:00
message += "[CR][CR]Are you sure?[CR][CR]"
confirm_dialog = SafeDeleteDialog("SafeDeleteDialog.xml", PLUGINPATH, "default", "720p")
confirm_dialog.message = message
confirm_dialog.heading = "Confirm delete files?"
confirm_dialog.doModal()
log.debug("safe_delete_confirm_dialog: {0}".format(confirm_dialog.confirm))
2020-04-14 13:24:01 +10:00
if confirm_dialog.confirm:
url = "{server}/jellyfin_safe_delete/delete_item_action"
2020-04-14 13:24:01 +10:00
playback_info = {
'item_id': item_id,
'action_token': action_token
}
2020-06-21 11:27:09 +10:00
delete_action = downloadUtils.download_url(url, method="POST", post_body=playback_info)
log.debug("Delete result action: {0}".format(delete_action))
if not delete_action:
dialog.ok("Error", "Error deleting files", "Error in responce from server")
elif not delete_action.get("result"):
dialog.ok("Error", "Error deleting files", delete_action["message"])
2020-04-14 13:24:01 +10:00
else:
dialog.ok("Deleted", "Files deleted")
else:
dialog.ok("Error", "Error getting safe delete confirmation")
2020-04-14 19:31:55 +10:00
elif selected_action == "show_extras":
u = "{server}/Users/{userid}/Items/" + item_id + "/SpecialFeatures"
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Videos")
2020-04-14 19:31:55 +10:00
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
xbmc.executebuiltin(built_in_command)
2020-04-14 13:24:01 +10:00
elif selected_action == "view_season":
2018-11-18 13:16:47 +11:00
xbmc.executebuiltin("Dialog.Close(all,true)")
parent_id = result["ParentId"]
2018-12-21 11:33:41 +11:00
series_id = result["SeriesId"]
u = ('{server}/Shows/' + series_id +
2018-12-21 11:33:41 +11:00
'/Episodes'
'?userId={userid}' +
'&seasonId=' + parent_id +
'&IsVirtualUnAired=false' +
'&IsMissing=false' +
'&Fields=SpecialEpisodeNumbers,{field_filters}' +
2018-12-21 11:33:41 +11:00
'&format=json')
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Season")
2018-12-21 11:33:41 +11:00
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
xbmc.executebuiltin(built_in_command)
2017-08-19 11:08:15 +10:00
elif selected_action == "view_series":
xbmc.executebuiltin("Dialog.Close(all,true)")
2019-06-02 20:09:18 +10:00
series_id = result["SeriesId"]
if not series_id:
series_id = item_id
u = ('{server}/Shows/' + series_id +
'/Seasons'
'?userId={userid}' +
'&Fields={field_filters}' +
'&format=json')
2019-06-02 20:09:18 +10:00
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Series")
2019-06-02 20:09:18 +10:00
if xbmc.getCondVisibility("Window.IsActive(home)"):
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
else:
built_in_command = 'Container.Update(' + action_url + ')'
xbmc.executebuiltin(built_in_command)
elif selected_action == "refresh_images":
CacheArtwork().delete_cached_images(item_id)
2019-08-25 08:44:25 +10:00
elif selected_action == "info":
2019-09-06 07:25:06 +10:00
xbmc.executebuiltin("Dialog.Close(all,true)")
2019-08-25 08:44:25 +10:00
xbmc.executebuiltin("Action(info)")
2020-06-21 11:27:09 +10:00
2017-12-25 18:22:23 +11:00
def populate_listitem(item_id):
log.debug("populate_listitem: {0}".format(item_id))
2017-12-25 18:22:23 +11:00
url = "{server}/Users/{userid}/Items/" + item_id + "?format=json"
result = downloadUtils.download_url(url)
log.debug("populate_listitem item info: {0}".format(result))
2017-12-26 21:04:14 +11:00
2018-10-26 14:04:54 +11:00
item_title = result.get("Name", string_load(30280))
2017-12-25 18:22:23 +11:00
list_item = xbmcgui.ListItem(label=item_title)
2020-06-21 11:27:09 +10:00
server = downloadUtils.get_server()
2017-12-25 18:22:23 +11:00
2020-06-21 11:27:09 +10:00
art = get_art(result, server=server)
2017-12-25 18:22:23 +11:00
list_item.setIconImage(art['thumb']) # back compat
list_item.setProperty('fanart_image', art['fanart']) # back compat
list_item.setProperty('discart', art['discart']) # not avail to setArt
list_item.setArt(art)
list_item.setProperty('IsPlayable', 'false')
2017-12-25 18:22:23 +11:00
list_item.setProperty('IsFolder', 'false')
list_item.setProperty('id', result.get("Id"))
# play info
details = {
'title': item_title,
'plot': result.get("Overview")
}
list_item.setInfo("Video", infoLabels=details)
return list_item
2020-06-21 11:27:09 +10:00
def show_content(params):
log.debug("showContent Called: {0}".format(params))
2017-03-11 21:07:08 +11:00
item_type = params.get("item_type")
2018-09-18 14:29:54 +10:00
settings = xbmcaddon.Addon()
group_movies = settings.getSetting('group_movies') == "true"
if item_type.lower().find("movie") == -1:
group_movies = False
content_url = ("{server}/Users/{userid}/Items" +
2020-06-21 11:27:09 +10:00
"?format=json" +
"&ImageTypeLimit=1" +
"&IsMissing=False" +
"&Fields={field_filters}" +
'&CollapseBoxSetItems=' + str(group_movies) +
'&GroupItemsIntoCollections=' + str(group_movies) +
"&Recursive=true" +
'&SortBy=Name' +
'&SortOrder=Ascending' +
"&IsVirtualUnaired=false" +
"&IncludeItemTypes=" + item_type)
2017-03-11 21:07:08 +11:00
log.debug("showContent Content Url: {0}".format(content_url))
2020-06-21 11:27:09 +10:00
get_content(content_url, params)
2018-01-12 10:14:37 +11:00
2018-07-11 12:22:41 +10:00
def search_results_person(params):
handle = int(sys.argv[1])
person_id = params.get("person_id")
details_url = ('{server}/Users/{userid}/items' +
2018-07-11 12:22:41 +10:00
'?PersonIds=' + person_id +
'&Recursive=true' +
'&Fields={field_filters}' +
'&format=json')
2018-12-30 15:40:28 +11:00
params["name_format"] = "Episode|episode_name_format"
2020-06-21 11:27:09 +10:00
dir_items, detected_type, total_records = process_directory(details_url, None, params)
2018-07-11 12:22:41 +10:00
log.debug('search_results_person results: {0}'.format(dir_items))
log.debug('search_results_person detect_type: {0}'.format(detected_type))
2018-07-11 12:22:41 +10:00
if detected_type is not None:
# if the media type is not set then try to use the detected type
log.debug("Detected content type: {0}".format(detected_type))
2018-07-11 20:35:12 +10:00
content_type = None
2018-07-11 12:22:41 +10:00
if detected_type == "Movie":
content_type = 'movies'
2018-07-11 20:35:12 +10:00
elif detected_type == "Episode":
2018-07-11 12:22:41 +10:00
content_type = 'episodes'
2018-07-11 20:35:12 +10:00
elif detected_type == "Series":
content_type = 'tvshows'
elif detected_type == "Music" or detected_type == "Audio" or detected_type == "Musicalbum":
content_type = 'songs'
if content_type:
xbmcplugin.setContent(handle, content_type)
2018-07-11 12:22:41 +10:00
if dir_items is not None:
xbmcplugin.addDirectoryItems(handle, dir_items)
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
2020-06-21 11:27:09 +10:00
2018-07-11 12:22:41 +10:00
def search_results(params):
2017-12-27 23:10:54 +11:00
item_type = params.get('item_type')
2018-05-07 20:14:58 +10:00
query_string = params.get('query')
if query_string:
log.debug("query_string : {0}".format(query_string))
query_string = unquote(query_string)
log.debug("query_string : {0}".format(query_string))
2017-12-27 23:10:54 +11:00
2018-05-08 14:29:21 +10:00
item_type = item_type.lower()
if item_type == 'movie':
2018-10-26 14:04:54 +11:00
heading_type = string_load(30231)
2018-05-08 14:29:21 +10:00
content_type = 'movies'
elif item_type == 'series':
2018-10-26 14:04:54 +11:00
heading_type = string_load(30229)
2018-05-08 14:29:21 +10:00
content_type = 'tvshows'
elif item_type == 'episode':
2018-10-26 14:04:54 +11:00
heading_type = string_load(30235)
2018-05-08 14:29:21 +10:00
content_type = 'episodes'
params["name_format"] = "Episode|episode_name_format"
elif item_type == "music" or item_type == "audio" or item_type == "musicalbum":
heading_type = 'Music'
content_type = 'songs'
2018-07-11 12:22:41 +10:00
elif item_type == "person":
2018-05-08 14:29:21 +10:00
heading_type = 'Artists'
content_type = 'artists'
else:
heading_type = item_type
2018-05-08 14:29:21 +10:00
content_type = 'video'
2017-12-27 23:10:54 +11:00
2018-05-07 20:14:58 +10:00
handle = int(sys.argv[1])
2017-12-27 23:10:54 +11:00
2018-05-07 20:14:58 +10:00
if not query_string:
home_window = HomeWindow()
2020-06-21 11:27:09 +10:00
last_search = home_window.get_property("last_search")
2018-05-07 20:14:58 +10:00
kb = xbmc.Keyboard()
2018-10-26 14:04:54 +11:00
kb.setHeading(heading_type.capitalize() + ' ' + string_load(30246).lower())
2018-05-07 20:14:58 +10:00
kb.setDefault(last_search)
kb.doModal()
if kb.isConfirmed():
user_input = kb.getText().strip()
else:
return
2017-12-27 23:10:54 +11:00
2020-06-21 11:27:09 +10:00
home_window.set_property("last_search", user_input)
log.debug('searchResults Called: {0}'.format(params))
2018-05-07 20:14:58 +10:00
query = user_input
else:
query = query_string
query = quote(query)
log.debug("query : {0}".format(query))
2018-07-11 20:35:12 +10:00
if (not item_type) or (not query):
return
# show a progress indicator if needed
settings = xbmcaddon.Addon()
progress = None
if settings.getSetting('showLoadProgress') == "true":
progress = xbmcgui.DialogProgress()
2018-10-26 14:04:54 +11:00
progress.create(string_load(30112))
progress.update(0, string_load(30113))
2019-07-22 09:26:57 +10:00
# what type of search
if item_type == "person":
search_url = ("{server}/Persons" +
2019-07-22 09:26:57 +10:00
"?searchTerm=" + query +
"&IncludePeople=true" +
"&IncludeMedia=false" +
"&IncludeGenres=false" +
"&IncludeStudios=false" +
"&IncludeArtists=false" +
"&Limit=16" +
"&Fields=PrimaryImageAspectRatio,BasicSyncInfo,ProductionYear" +
"&Recursive=true" +
"&EnableTotalRecordCount=false" +
"&ImageTypeLimit=1" +
"&userId={userid}")
2020-06-21 11:27:09 +10:00
person_search_results = dataManager.get_content(search_url)
log.debug("Person Search Result : {0}".format(person_search_results))
2019-07-22 09:26:57 +10:00
if person_search_results is None:
return
2019-07-22 09:26:57 +10:00
person_items = person_search_results.get("Items", [])
2020-06-21 11:27:09 +10:00
server = downloadUtils.get_server()
2018-07-11 12:22:41 +10:00
list_items = []
2019-07-22 09:26:57 +10:00
for item in person_items:
person_id = item.get('Id')
2018-07-11 12:22:41 +10:00
person_name = item.get('Name')
2020-06-21 11:27:09 +10:00
person_thumbnail = downloadUtils.get_artwork(item, "Primary", server=server)
2018-07-11 12:22:41 +10:00
action_url = sys.argv[0] + "?mode=NEW_SEARCH_PERSON&person_id=" + person_id
list_item = xbmcgui.ListItem(label=person_name)
list_item.setProperty("id", person_id)
art_links = {}
art_links["icon"] = "DefaultActor.png"
2018-07-11 12:22:41 +10:00
if person_thumbnail:
art_links["thumb"] = person_thumbnail
art_links["poster"] = person_thumbnail
list_item.setArt(art_links)
2018-07-11 12:22:41 +10:00
item_tupple = (action_url, list_item, True)
list_items.append(item_tupple)
xbmcplugin.setContent(handle, 'artists')
xbmcplugin.addDirectoryItems(handle, list_items)
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
2018-07-11 12:22:41 +10:00
else:
search_url = ("{server}/Users/{userid}/Items" +
2019-07-22 09:26:57 +10:00
"?searchTerm=" + query +
"&IncludePeople=false" +
"&IncludeMedia=true" +
"&IncludeGenres=false" +
"&IncludeStudios=false" +
"&IncludeArtists=false" +
"&IncludeItemTypes=" + item_type +
"&Limit=16" +
"&Fields={field_filters}" +
"&Recursive=true" +
"&EnableTotalRecordCount=false" +
"&ImageTypeLimit=1")
# set content type
xbmcplugin.setContent(handle, content_type)
2020-06-21 11:27:09 +10:00
dir_items, detected_type, total_records = process_directory(search_url, progress, params)
xbmcplugin.addDirectoryItems(handle, dir_items)
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
if progress is not None:
2018-10-26 14:04:54 +11:00
progress.update(100, string_load(30125))
progress.close()
2020-06-21 11:27:09 +10:00
def play_action(params):
2017-07-08 10:34:30 +10:00
log.debug("== ENTER: PLAY ==")
2017-04-13 06:58:25 +10:00
log.debug("PLAY ACTION PARAMS: {0}".format(params))
2017-05-25 18:16:01 +10:00
item_id = params.get("item_id")
2017-04-13 06:58:25 +10:00
2020-09-05 17:49:18 -04:00
auto_resume = params.get("auto_resume", "-1")
if auto_resume == 'None':
auto_resume = '-1'
if auto_resume:
auto_resume = int(auto_resume)
else:
auto_resume = -1
log.debug("AUTO_RESUME: {0}".format(auto_resume))
2017-04-13 06:58:25 +10:00
2020-06-21 11:27:09 +10:00
force_transcode = params.get("force_transcode", None) is not None
log.debug("FORCE_TRANSCODE: {0}".format(force_transcode))
media_source_id = params.get("media_source_id", "")
log.debug("media_source_id: {0}".format(media_source_id))
2017-12-14 13:43:23 +11:00
subtitle_stream_index = params.get("subtitle_stream_index")
log.debug("subtitle_stream_index: {0}".format(subtitle_stream_index))
audio_stream_index = params.get("audio_stream_index")
log.debug("audio_stream_index: {0}".format(audio_stream_index))
2017-12-14 13:43:23 +11:00
action = params.get("action", "play")
2017-04-13 06:58:25 +10:00
# set the current playing item id
# set all the playback info, this will be picked up by the service
# the service will then start the playback
xbmc.Player().stop()
play_info = {}
play_info["action"] = action
2017-12-14 13:43:23 +11:00
play_info["item_id"] = item_id
play_info["auto_resume"] = str(auto_resume)
2020-06-21 11:27:09 +10:00
play_info["force_transcode"] = force_transcode
play_info["media_source_id"] = media_source_id
play_info["subtitle_stream_index"] = subtitle_stream_index
play_info["audio_stream_index"] = audio_stream_index
log.info("Sending jellycon_play_action : {0}".format(play_info))
play_file(play_info)
2017-12-13 07:32:44 +11:00
2020-06-21 11:27:09 +10:00
def play_item_trailer(item_id):
2017-12-13 07:32:44 +11:00
log.debug("== ENTER: playTrailer ==")
url = ("{server}/Users/{userid}/Items/%s/LocalTrailers?format=json" % item_id)
2017-12-13 07:32:44 +11:00
result = downloadUtils.download_url(url)
if result is None:
return
log.debug("LocalTrailers {0}".format(result))
count = 1
2017-12-13 07:32:44 +11:00
trailer_names = []
2017-12-13 07:32:44 +11:00
trailer_list = []
for trailer in result:
info = {}
info["type"] = "local"
name = trailer.get("Name")
while not name or name in trailer_names:
name = "Trailer " + str(count)
count += 1
info["name"] = name
2017-12-13 07:32:44 +11:00
info["id"] = trailer.get("Id")
count += 1
trailer_names.append(name)
2017-12-13 07:32:44 +11:00
trailer_list.append(info)
url = ("{server}/Users/{userid}/Items/%s?format=json&Fields=RemoteTrailers" % item_id)
result = downloadUtils.download_url(url)
log.debug("RemoteTrailers: {0}".format(result))
count = 1
2017-12-13 07:32:44 +11:00
if result is None:
return
2017-12-13 07:32:44 +11:00
remote_trailers = result.get("RemoteTrailers", [])
for trailer in remote_trailers:
info = {}
info["type"] = "remote"
url = trailer.get("Url", "none")
2019-02-09 19:26:27 +11:00
if url.lower().find("youtube") != -1:
2017-12-13 07:32:44 +11:00
info["url"] = url
name = trailer.get("Name")
while not name or name in trailer_names:
name = "Trailer " + str(count)
count += 1
info["name"] = name
trailer_names.append(name)
2017-12-13 07:32:44 +11:00
trailer_list.append(info)
log.debug("TrailerList: {0}".format(trailer_list))
2017-12-13 07:32:44 +11:00
trailer_text = []
for trailer in trailer_list:
name = trailer.get("name") + " (" + trailer.get("type") + ")"
trailer_text.append(name)
dialog = xbmcgui.Dialog()
2018-10-26 14:04:54 +11:00
resp = dialog.select(string_load(30308), trailer_text)
2017-12-13 07:32:44 +11:00
if resp > -1:
trailer = trailer_list[resp]
log.debug("SelectedTrailer: {0}".format(trailer))
2017-12-13 07:32:44 +11:00
if trailer.get("type") == "local":
params = {}
params["item_id"] = trailer.get("id")
2020-06-21 11:27:09 +10:00
play_action(params)
2017-12-13 07:32:44 +11:00
elif trailer.get("type") == "remote":
youtube_id = trailer.get("url").rsplit('=', 1)[1]
youtube_plugin = "RunPlugin(plugin://plugin.video.youtube/play/?video_id=%s)" % youtube_id
log.debug("youtube_plugin: {0}".format(youtube_plugin))
xbmc.executebuiltin(youtube_plugin)