Files
jellycon/resources/lib/dir_functions.py

471 lines
20 KiB
Python

from __future__ import (
division, absolute_import, print_function, unicode_literals
)
import sys
import re
import xbmcaddon
import xbmcplugin
import xbmcgui
from six.moves.urllib.parse import quote, unquote, parse_qsl
from .datamanager import DataManager
from .lazylogger import LazyLogger
from .item_functions import add_gui_item, ItemDetails
from .tracking import timer
from .utils import (
send_event_notification, translate_string,
load_user_details, get_default_filters
)
log = LazyLogger(__name__)
@timer
def get_content(url, params):
log.debug("== ENTER: getContent ==")
default_sort = params.get("sort")
media_type = params.get("media_type", None)
if not media_type:
xbmcgui.Dialog().ok(translate_string(30135), translate_string(30139))
log.debug("URL: {0}".format(url))
log.debug("MediaType: {0}".format(media_type))
pluginhandle = int(sys.argv[1])
settings = xbmcaddon.Addon()
# determine view type, map it from media type to view type
view_type = ""
content_type = ""
media_type = str(media_type).lower().strip()
url_params = dict(parse_qsl(url))
if media_type.startswith("movie"):
view_type = "Movies"
content_type = 'movies'
elif media_type == "musicalbums":
view_type = "Albums"
content_type = 'albums'
elif media_type == "musicartists":
view_type = "Artists"
content_type = 'artists'
elif media_type == "musicartist":
view_type = "Albums"
content_type = 'albums'
elif media_type == "music" or media_type == "audio" or media_type == "musicalbum":
view_type = "Music"
content_type = 'songs'
elif media_type.startswith("boxsets"):
view_type = "Movies"
content_type = 'sets'
elif media_type.startswith("boxset"):
view_type = "BoxSets"
content_type = 'movies'
elif media_type == "tvshows":
view_type = "Series"
content_type = 'tvshows'
elif media_type == "series":
view_type = "Seasons"
content_type = 'seasons'
elif media_type == "season" or media_type == "episodes":
view_type = "Episodes"
content_type = 'episodes'
elif media_type == "playlists":
view_type = "Playlists"
elif media_type == "musicvideos":
view_type = "Music Videos"
content_type = 'musicvideos'
elif media_type == "mixed":
content_type = 'videos'
log.debug("media_type:{0} content_type:{1} view_type:{2} ".format(media_type, content_type, view_type))
# show a progress indicator if needed
progress = None
if settings.getSetting('showLoadProgress') == "true":
progress = xbmcgui.DialogProgress()
progress.create(translate_string(30112))
progress.update(0, translate_string(30113))
# update url for paging
start_index = int(url_params.get("StartIndex", 0))
url_limit = url_params.get("Limit")
movie_page_limit = int(settings.getSetting('moviePageSize'))
show_page_limit = int(settings.getSetting('showPageSize'))
url_prev = None
url_next = None
if not url_limit or start_index > 0:
if movie_page_limit > 0 and media_type.startswith("movie"):
log.debug("UPDATING NEXT URL: {0}".format(url))
log.debug("current_start : {0}".format(start_index))
if start_index > 0:
prev_index = start_index - movie_page_limit
if prev_index < 0:
prev_index = 0
url_prev = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(prev_index), url)
url_next = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(start_index + movie_page_limit), url)
log.debug("UPDATING NEXT URL: {0}".format(url_next))
else:
log.debug("ADDING NEXT URL: {0}".format(url))
url_next = url + "&StartIndex=" + str(start_index + movie_page_limit) + "&Limit=" + str(movie_page_limit)
url = url + "&StartIndex=" + str(start_index) + "&Limit=" + str(movie_page_limit)
log.debug("ADDING NEXT URL: {0}".format(url_next))
if show_page_limit > 0 and media_type.startswith("tvshow"):
log.debug("UPDATING NEXT URL: {0}".format(url))
log.debug("current_start : {0}".format(start_index))
if start_index > 0:
prev_index = start_index - show_page_limit
if prev_index < 0:
prev_index = 0
url_prev = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(prev_index), url)
url_next = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(start_index + show_page_limit), url)
log.debug("UPDATING NEXT URL: {0}".format(url_next))
else:
log.debug("ADDING NEXT URL: {0}".format(url))
url_next = url + "&StartIndex=" + str(start_index + show_page_limit) + "&Limit=" + str(show_page_limit)
url = url + "&StartIndex=" + str(start_index) + "&Limit=" + str(show_page_limit)
log.debug("ADDING NEXT URL: {0}".format(url_next))
use_cache = params.get("use_cache", "true") == "true"
dir_items, detected_type, total_records = process_directory(url, progress, params, use_cache)
if dir_items is None:
return
log.debug("total_records: {0}".format(total_records))
if not url_limit or start_index > 0:
# add paging items
if movie_page_limit > 0 and media_type.startswith("movie"):
if url_prev:
list_item = xbmcgui.ListItem("Prev Page (" + str(start_index - movie_page_limit + 1) + "-" + str(start_index) +
" of " + str(total_records) + ")")
u = sys.argv[0] + "?url=" + quote(url_prev) + "&mode=GET_CONTENT&media_type=movies"
log.debug("ADDING PREV ListItem: {0} - {1}".format(u, list_item))
dir_items.insert(0, (u, list_item, True))
if start_index + movie_page_limit < total_records:
upper_count = start_index + (movie_page_limit * 2)
if upper_count > total_records:
upper_count = total_records
list_item = xbmcgui.ListItem("Next Page (" + str(start_index + movie_page_limit + 1) + "-" +
str(upper_count) + " of " + str(total_records) + ")")
u = sys.argv[0] + "?url=" + quote(url_next) + "&mode=GET_CONTENT&media_type=movies"
log.debug("ADDING NEXT ListItem: {0} - {1}".format(u, list_item))
dir_items.append((u, list_item, True))
# add paging items
if show_page_limit > 0 and media_type.startswith("tvshow"):
if url_prev:
list_item = xbmcgui.ListItem("Prev Page (" + str(start_index - show_page_limit + 1) + "-" + str(start_index) +
" of " + str(total_records) + ")")
u = sys.argv[0] + "?url=" + quote(url_prev) + "&mode=GET_CONTENT&media_type=tvshows"
log.debug("ADDING PREV ListItem: {0} - {1}".format(u, list_item))
dir_items.insert(0, (u, list_item, True))
if start_index + show_page_limit < total_records:
upper_count = start_index + (show_page_limit * 2)
if upper_count > total_records:
upper_count = total_records
list_item = xbmcgui.ListItem("Next Page (" + str(start_index + show_page_limit + 1) + "-" +
str(upper_count) + " of " + str(total_records) + ")")
u = sys.argv[0] + "?url=" + quote(url_next) + "&mode=GET_CONTENT&media_type=tvshows"
log.debug("ADDING NEXT ListItem: {0} - {1}".format(u, list_item))
dir_items.append((u, list_item, True))
# set the Kodi content type
if content_type:
xbmcplugin.setContent(pluginhandle, content_type)
elif 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))
if detected_type == "Movie":
view_type = "Movies"
content_type = 'movies'
if detected_type == "Episode":
view_type = "Episodes"
content_type = 'episodes'
xbmcplugin.setContent(pluginhandle, content_type)
# set the sort items
if movie_page_limit > 0 and media_type.startswith("movie"):
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
elif show_page_limit > 0 and media_type.startswith("tvshow"):
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
else:
set_sort(pluginhandle, view_type, default_sort)
xbmcplugin.addDirectoryItems(pluginhandle, dir_items)
xbmcplugin.endOfDirectory(pluginhandle, cacheToDisc=False)
# set the view based on saved value
view_key = "view-" + content_type
view_id = settings.getSetting(view_key)
if view_id:
log.debug("Setting view for type:{0} to id:{1}".format(view_key, view_id))
display_items_notification = {"view_id": view_id}
send_event_notification("set_view", display_items_notification)
else:
log.debug("No view id for view type:{0}".format(view_key))
if progress is not None:
progress.update(100, translate_string(30125))
progress.close()
return
def set_sort(pluginhandle, view_type, default_sort):
log.debug("SETTING_SORT for media type: {0}".format(view_type))
if default_sort == "none":
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
sorting_order_mapping = {
"1": xbmcplugin.SORT_METHOD_UNSORTED,
"2": xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE,
"3": xbmcplugin.SORT_METHOD_VIDEO_YEAR,
"4": xbmcplugin.SORT_METHOD_DATEADDED,
"5": xbmcplugin.SORT_METHOD_GENRE,
"6": xbmcplugin.SORT_METHOD_LABEL,
"7": xbmcplugin.SORT_METHOD_VIDEO_RATING
}
settings = xbmcaddon.Addon()
preset_sort_order = settings.getSetting("sort-" + view_type)
log.debug("SETTING_SORT preset_sort_order: {0}".format(preset_sort_order))
if preset_sort_order in sorting_order_mapping:
xbmcplugin.addSortMethod(pluginhandle, sorting_order_mapping[preset_sort_order])
if view_type == "BoxSets":
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE)
elif view_type == "Episodes":
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_EPISODE)
elif view_type == "Music":
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_TRACKNUM)
else:
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_DATEADDED)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_GENRE)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_NONE)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_RATING)
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
@timer
def process_directory(url, progress, params, use_cache_data=False):
log.debug("== ENTER: processDirectory ==")
data_manager = DataManager()
settings = xbmcaddon.Addon()
server = settings.getSetting('server_address')
user_details = load_user_details()
user_id = user_details.get('user_id')
name_format = params.get("name_format", None)
name_format_type = None
if name_format is not None:
name_format = unquote(name_format)
tokens = name_format.split("|")
if len(tokens) == 2:
name_format_type = tokens[0]
name_format = settings.getSetting(tokens[1])
else:
name_format_type = None
name_format = None
gui_options = {}
gui_options["server"] = server
gui_options["name_format"] = name_format
gui_options["name_format_type"] = name_format_type
use_cache = settings.getSetting("use_cache") == "true" and use_cache_data
default_filters = get_default_filters()
# Fix skin shortcuts from pre-0.5.0
item_limit = int(settings.getSetting("show_x_filtered_items"))
url = url.replace('{server}', '')
url = url.replace('{field_filters}', default_filters)
url = url.replace('{ItemLimit}', str(item_limit))
# Need to replace at runtime so it always pulls the current user
url = unquote(url)
url = url.replace('{userid}', user_id)
cache_file, item_list, total_records, cache_thread = data_manager.get_items(url, gui_options, use_cache)
# flatten single season
# if there is only one result and it is a season and you have flatten single season turned on then
# build a new url, set the content media type and call get content again
flatten_single_season = settings.getSetting("flatten_single_season") == "true"
if flatten_single_season and len(item_list) == 1 and item_list[0].item_type == "Season":
season_id = item_list[0].id
series_id = item_list[0].series_id
season_url = ('/Shows/' + series_id +
'/Episodes'
'?userId={userid}' +
'&seasonId=' + season_id +
'&IsVirtualUnAired=false' +
'&IsMissing=false' +
'&Fields=SpecialEpisodeNumbers,{}'.format(default_filters) +
'&format=json')
if progress is not None:
progress.close()
params["media_type"] = "Episodes"
get_content(season_url, params)
return None, None, None
hide_unwatched_details = settings.getSetting('hide_unwatched_details') == 'true'
display_options = {}
display_options["addCounts"] = settings.getSetting("addCounts") == 'true'
display_options["addResumePercent"] = settings.getSetting("addResumePercent") == 'true'
display_options["addSubtitleAvailable"] = settings.getSetting("addSubtitleAvailable") == 'true'
display_options["addUserRatings"] = settings.getSetting("add_user_ratings") == 'true'
show_empty_folders = settings.getSetting("show_empty_folders") == 'true'
item_count = len(item_list)
current_item = 1
first_season_item = None
total_unwatched = 0
total_episodes = 0
total_watched = 0
detected_type = None
dir_items = []
OnlyTotallyUnwatchedTvShow = params.get("OnlyTotallyUnwatchedTvShow", None)
for item_details in item_list:
if OnlyTotallyUnwatchedTvShow == "1" and item_details.watched_episodes > 0:
continue
item_details.total_items = item_count
if progress is not None:
percent_done = (float(current_item) / float(item_count)) * 100
progress.update(int(percent_done), translate_string(30126) + str(current_item))
current_item = current_item + 1
if detected_type is not None:
if item_details.item_type != detected_type:
detected_type = "mixed"
else:
detected_type = item_details.item_type
if item_details.item_type == "Season" and first_season_item is None:
log.debug("Setting First Season to : {0}".format(item_details.__dict__))
first_season_item = item_details
total_unwatched += item_details.unwatched_episodes
total_episodes += item_details.total_episodes
total_watched += item_details.watched_episodes
# if set, for unwatched episodes dont show some of the info
if hide_unwatched_details and item_details.item_type == "Episode" and item_details.play_count == 0:
item_details.plot = "[Spoiler Alert]"
item_details.art["poster"] = item_details.art["tvshow.poster"]
item_details.art["thumb"] = item_details.art["tvshow.poster"]
if item_details.is_folder is True:
if item_details.item_type == "Series":
u = ('/Shows/' + item_details.id +
'/Seasons'
'?userId={userid}' +
'&Fields={}'.format(default_filters) +
'&format=json')
if not show_empty_folders:
u = u + '&isMissing=False'
elif item_details.item_type == "Season":
u = ('/Shows/' + item_details.series_id +
'/Episodes'
'?userId={userid}' +
'&seasonId=' + item_details.id +
'&IsVirtualUnAired=false' +
'&IsMissing=false' +
'&Fields=SpecialEpisodeNumbers,{}'.format(default_filters) +
'&format=json')
else:
u = ('/Users/{userid}/items' +
'?ParentId=' + item_details.id +
'&IsVirtualUnAired=false' +
'&IsMissing=false' +
'&Fields={}'.format(default_filters) +
'&format=json')
default_sort = item_details.item_type == "Playlist"
if show_empty_folders or item_details.recursive_item_count != 0:
gui_item = add_gui_item(u, item_details, display_options, default_sort=default_sort)
if gui_item:
dir_items.append(gui_item)
else:
log.debug("Dropping empty folder item : {0}".format(item_details.__dict__))
elif item_details.item_type == "MusicArtist":
u = ('/Users/{userid}/items' +
'?ArtistIds=' + item_details.id +
'&IncludeItemTypes=MusicAlbum' +
'&CollapseBoxSetItems=false' +
'&Recursive=true' +
'&format=json')
gui_item = add_gui_item(u, item_details, display_options)
if gui_item:
dir_items.append(gui_item)
else:
u = item_details.id
gui_item = add_gui_item(u, item_details, display_options, folder=False)
if gui_item:
dir_items.append(gui_item)
# add the all episodes item
show_all_episodes = settings.getSetting('show_all_episodes') == 'true'
if (show_all_episodes
and first_season_item is not None
and len(dir_items) > 1
and first_season_item.series_id is not None):
series_url = ('/Shows/' + first_season_item.series_id +
'/Episodes'
'?userId={userid}' +
'&IsVirtualUnAired=false' +
'&IsMissing=false' +
'&Fields=SpecialEpisodeNumbers,{}'.format(default_filters) +
'&format=json')
played = 0
overlay = "7"
if total_unwatched == 0:
played = 1
overlay = "6"
item_details = ItemDetails()
item_details.id = first_season_item.id
item_details.name = translate_string(30290)
item_details.art = first_season_item.art
item_details.play_count = played
item_details.overlay = overlay
item_details.name_format = "Episode|episode_name_format"
item_details.series_name = first_season_item.series_name
item_details.item_type = "Season"
item_details.unwatched_episodes = total_unwatched
item_details.total_episodes = total_episodes
item_details.watched_episodes = total_watched
item_details.mode = "GET_CONTENT"
gui_item = add_gui_item(series_url, item_details, display_options, folder=True)
if gui_item:
dir_items.append(gui_item)
if cache_thread is not None:
cache_thread.start()
return dir_items, detected_type, total_records