diff --git a/resources/lib/downloader.py b/resources/lib/downloader.py index 2094bad0..f4abb151 100644 --- a/resources/lib/downloader.py +++ b/resources/lib/downloader.py @@ -2,20 +2,18 @@ ################################################################################################# -import json import logging import Queue import threading import os -from datetime import datetime import xbmc import xbmcvfs import xbmcaddon import requests -from helper.utils import should_stop, delete_folder -from helper import settings, stop, event, window, kodi_version, unzip, create_id +from helper.utils import delete_folder +from helper import settings, stop, event, window, unzip, create_id from jellyfin import Jellyfin from jellyfin.core import api from jellyfin.core.exceptions import HTTPException @@ -28,6 +26,7 @@ CACHE = xbmc.translatePath(os.path.join(xbmcaddon.Addon(id='plugin.video.jellyfi ################################################################################################# + def get_jellyfinserver_url(handler): if handler.startswith('/'): @@ -35,27 +34,33 @@ def get_jellyfinserver_url(handler): handler = handler[1:] LOG.warn("handler starts with /: %s", handler) - return "{server}/emby/%s" % handler + return "{server}/emby/%s" % handler + def browse_info(): - return ( - "DateCreated,EpisodeCount,SeasonCount,Path,Genres,Studios,Taglines,MediaStreams,Overview,Etag," - "ProductionLocations,Width,Height,RecursiveItemCount,ChildCount" - ) + return ( + "DateCreated,EpisodeCount,SeasonCount,Path,Genres,Studios,Taglines,MediaStreams,Overview,Etag," + "ProductionLocations,Width,Height,RecursiveItemCount,ChildCount" + ) + def _http(action, url, request={}, server_id=None): request.update({'url': url, 'type': action}) return Jellyfin(server_id)['http/request'](request) + def _get(handler, params=None, server_id=None): - return _http("GET", get_jellyfinserver_url(handler), {'params': params}, server_id) + return http("GET", get_jellyfinserver_url(handler), {'params': params}, server_id) + def _post(handler, json=None, params=None, server_id=None): - return _http("POST", get_jellyfinserver_url(handler), {'params': params, 'json': json}, server_id) + return http("POST", get_jellyfinserver_url(handler), {'params': params, 'json': json}, server_id) + def _delete(handler, params=None, server_id=None): - return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id) + return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id) + def validate_view(library_id, item_id): @@ -73,13 +78,15 @@ def validate_view(library_id, item_id): return True if len(result['Items']) else False + def get_single_item(parent_id, media): - return _get("Users/{UserId}/Items", { - 'ParentId': parent_id, - 'Recursive': True, - 'Limit': 1, - 'IncludeItemTypes': media - }) + return _get("Users/{UserId}/Items", { + 'ParentId': parent_id, + 'Recursive': True, + 'Limit': 1, + 'IncludeItemTypes': media + }) + def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None, sort=None, sort_order=None, filters=None, extra=None, server_id=None): @@ -99,9 +106,7 @@ def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None, 'Fields': browse_info() } if filters: - if 'Boxsets' in filters: - filters.remove('Boxsets') params['CollapseBoxSetItems'] = settings('groupedSets.bool') @@ -116,13 +121,15 @@ def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None, if extra is not None: params.update(extra) - return _get("Users/{UserId}/Items", params, server_id) + return _get("Users/{UserId}/Items", params, server_id) + def get_movies_by_boxset(boxset_id): for items in get_items(boxset_id, "Movie"): yield items + def get_episode_by_show(show_id): query = { @@ -137,6 +144,7 @@ def get_episode_by_show(show_id): for items in _get_items(query): yield items + def get_episode_by_season(show_id, season_id): query = { @@ -152,6 +160,7 @@ def get_episode_by_season(show_id, season_id): for items in _get_items(query): yield items + def get_items(parent_id, item_type=None, basic=False, params=None): query = { @@ -176,6 +185,7 @@ def get_items(parent_id, item_type=None, basic=False, params=None): for items in _get_items(query): yield items + def get_artists(parent_id=None, basic=False, params=None, server_id=None): query = { @@ -201,6 +211,7 @@ def get_artists(parent_id=None, basic=False, params=None, server_id=None): for items in _get_items(query, server_id): yield items + def get_albums_by_artist(artist_id, basic=False): params = { @@ -210,6 +221,7 @@ def get_albums_by_artist(artist_id, basic=False): for items in get_items(None, "MusicAlbum", basic, params): yield items + def get_songs_by_artist(artist_id, basic=False): params = { @@ -219,6 +231,7 @@ def get_songs_by_artist(artist_id, basic=False): for items in get_items(None, "Audio", basic, params): yield items + @stop() def _get_items(query, server_id=None): @@ -263,6 +276,7 @@ def _get_items(query, server_id=None): del items['Items'][:] index += LIMIT + class GetItemWorker(threading.Thread): is_done = False @@ -275,10 +289,8 @@ class GetItemWorker(threading.Thread): threading.Thread.__init__(self) def run(self): - with requests.Session() as s: while True: - try: item_ids = self.queue.get(timeout=1) except Queue.Empty: @@ -320,6 +332,7 @@ class GetItemWorker(threading.Thread): if window('jellyfin_should_stop.bool'): break + class TheVoid(object): def __init__(self, method, data): @@ -359,6 +372,7 @@ class TheVoid(object): xbmc.sleep(100) LOG.info("--[ void/%s ]", self.data['VoidName']) + def get_objects(src, filename): ''' Download objects dependency to temp cache folder. @@ -383,7 +397,7 @@ def get_objects(src, filename): LOG.error(error) response = requests.get(src, stream=True, verify=False) - except Exception as error: + except Exception: raise dl = xbmcvfs.File(path, 'w') diff --git a/resources/lib/helper/api.py b/resources/lib/helper/api.py index 3b43c01b..068870a6 100644 --- a/resources/lib/helper/api.py +++ b/resources/lib/helper/api.py @@ -2,8 +2,6 @@ ################################################################################################## -import json -import datetime import logging from . import settings @@ -16,8 +14,6 @@ LOG = logging.getLogger("JELLYFIN."+__name__) class API(object): - - def __init__(self, item, server=None): ''' Get item information in special cases. @@ -71,7 +67,7 @@ class API(object): return cast def media_streams(self, video, audio, subtitles): - return { + return { 'video': video or [], 'audio': audio or [], 'subtitle': subtitles or [] @@ -161,7 +157,6 @@ class API(object): def validate_studio(self, studio_name): # Convert studio for Kodi to properly detect them studios = { - 'abc (us)': "ABC", 'fox (us)': "FOX", 'mtv (us)': "MTV", diff --git a/resources/lib/jellyfin/core/api.py b/resources/lib/jellyfin/core/api.py index 04d966b3..d81a3a17 100644 --- a/resources/lib/jellyfin/core/api.py +++ b/resources/lib/jellyfin/core/api.py @@ -1,31 +1,30 @@ # -*- coding: utf-8 -*- - -################################################################################################# - def jellyfin_url(client, handler): - return "%s/emby/%s" % (client.config['auth.server'], handler) + return "%s/emby/%s" % (client.config['auth.server'], handler) + def basic_info(): - return "Etag" + return "Etag" + def info(): - return ( - "Path,Genres,SortName,Studios,Writer,Taglines,LocalTrailerCount," - "OfficialRating,CumulativeRunTimeTicks,ItemCounts," - "Metascore,AirTime,DateCreated,People,Overview," - "CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations," - "Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers," - "MediaSources,VoteCount,RecursiveItemCount,PrimaryImageAspectRatio" - ) + return ( + "Path,Genres,SortName,Studios,Writer,Taglines,LocalTrailerCount," + "OfficialRating,CumulativeRunTimeTicks,ItemCounts," + "Metascore,AirTime,DateCreated,People,Overview," + "CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations," + "Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers," + "MediaSources,VoteCount,RecursiveItemCount,PrimaryImageAspectRatio" + ) + def music_info(): - return ( - "Etag,Genres,SortName,Studios,Writer," - "OfficialRating,CumulativeRunTimeTicks,Metascore," - "AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview,ItemCounts" - ) + return ( + "Etag,Genres,SortName,Studios,Writer," + "OfficialRating,CumulativeRunTimeTicks,Metascore," + "AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview,ItemCounts" + ) -################################################################################################# class API(object): @@ -37,16 +36,16 @@ class API(object): def _http(self, action, url, request={}): request.update({'type': action, 'handler': url}) - return self.client.request(request) + return self.client.request(request) def _get(self, handler, params=None): - return self._http("GET", handler, {'params': params}) + return self._http("GET", handler, {'params': params}) def _post(self, handler, json=None, params=None): - return self._http("POST", handler, {'params': params, 'json': json}) + return self._http("POST", handler, {'params': params, 'json': json}) def _delete(self, handler, params=None): - return self._http("DELETE", handler, {'params': params}) + return self._http("DELETE", handler, {'params': params}) ################################################################################################# @@ -55,48 +54,44 @@ class API(object): ################################################################################################# def try_server(self): - return self._get("System/Info/Public") + return self._get("System/Info/Public") def sessions(self, handler="", action="GET", params=None, json=None): - if action == "POST": - return self._post("Sessions%s" % handler, json, params) + return self._post("Sessions%s" % handler, json, params) elif action == "DELETE": - return self._delete("Sessions%s" % handler, params) + return self._delete("Sessions%s" % handler, params) else: - return self._get("Sessions%s" % handler, params) + return self._get("Sessions%s" % handler, params) def users(self, handler="", action="GET", params=None, json=None): - if action == "POST": - return self._post("Users/{UserId}%s" % handler, json, params) + return self._post("Users/{UserId}%s" % handler, json, params) elif action == "DELETE": - return self._delete("Users/{UserId}%s" % handler, params) + return self._delete("Users/{UserId}%s" % handler, params) else: - return self._get("Users/{UserId}%s" % handler, params) + return self._get("Users/{UserId}%s" % handler, params) def items(self, handler="", action="GET", params=None, json=None): - if action == "POST": - return self._post("Items%s" % handler, json, params) + return self._post("Items%s" % handler, json, params) elif action == "DELETE": - return self._delete("Items%s" % handler, params) + return self._delete("Items%s" % handler, params) else: - return self._get("Items%s" % handler, params) + return self._get("Items%s" % handler, params) def user_items(self, handler="", params=None): - return self.users("/Items%s" % handler, params=params) + return self.users("/Items%s" % handler, params=params) def shows(self, handler, params): - return self._get("Shows%s" % handler, params) + return self._get("Shows%s" % handler, params) def videos(self, handler): - return self._get("Videos%s" % handler) + return self._get("Videos%s" % handler) def artwork(self, item_id, art, max_width, ext="jpg", index=None): - if index is None: - return jellyfin_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext)) + return jellyfin_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext)) return jellyfin_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext)) @@ -107,238 +102,238 @@ class API(object): ################################################################################################# def get_users(self): - return self._get("Users") + return self._get("Users") def get_public_users(self): - return self._get("Users/Public") + return self._get("Users/Public") def get_user(self, user_id=None): - return self.users() if user_id is None else self._get("Users/%s" % user_id) + return self.users() if user_id is None else self._get("Users/%s" % user_id) def get_views(self): - return self.users("/Views") + return self.users("/Views") def get_media_folders(self): - return self.users("/Items") + return self.users("/Items") def get_item(self, item_id): - return self.users("/Items/%s" % item_id) + return self.users("/Items/%s" % item_id) def get_items(self, item_ids): - return self.users("/Items", params={ - 'Ids': ','.join(str(x) for x in item_ids), - 'Fields': info() - }) + return self.users("/Items", params={ + 'Ids': ','.join(str(x) for x in item_ids), + 'Fields': info() + }) def get_sessions(self): - return self.sessions(params={'ControllableByUserId': "{UserId}"}) + return self.sessions(params={'ControllableByUserId': "{UserId}"}) def get_device(self, device_id): - return self.sessions(params={'DeviceId': device_id}) + return self.sessions(params={'DeviceId': device_id}) def post_session(self, session_id, url, params=None, data=None): - return self.sessions("/%s/%s" % (session_id, url), "POST", params, data) + return self.sessions("/%s/%s" % (session_id, url), "POST", params, data) def get_images(self, item_id): - return self.items("/%s/Images" % item_id) + return self.items("/%s/Images" % item_id) def get_suggestion(self, media="Movie,Episode", limit=1): - return self.users("/Suggestions", { - 'Type': media, - 'Limit': limit - }) + return self.users("/Suggestions", params={ + 'Type': media, + 'Limit': limit + }) def get_recently_added(self, media=None, parent_id=None, limit=20): - return self.user_items("/Latest", { - 'Limit': limit, - 'UserId': "{UserId}", - 'IncludeItemTypes': media, - 'ParentId': parent_id, - 'Fields': info() - }) + return self.user_items("/Latest", { + 'Limit': limit, + 'UserId': "{UserId}", + 'IncludeItemTypes': media, + 'ParentId': parent_id, + 'Fields': info() + }) def get_next(self, index=None, limit=1): - return self.shows("/NextUp", { - 'Limit': limit, - 'UserId': "{UserId}", - 'StartIndex': None if index is None else int(index) - }) + return self.shows("/NextUp", { + 'Limit': limit, + 'UserId': "{UserId}", + 'StartIndex': None if index is None else int(index) + }) def get_adjacent_episodes(self, show_id, item_id): - return self.shows("/%s/Episodes" % show_id, { - 'UserId': "{UserId}", - 'AdjacentTo': item_id, - 'Fields': "Overview" - }) + return self.shows("/%s/Episodes" % show_id, { + 'UserId': "{UserId}", + 'AdjacentTo': item_id, + 'Fields': "Overview" + }) def get_genres(self, parent_id=None): - return self._get("Genres", { - 'ParentId': parent_id, - 'UserId': "{UserId}", - 'Fields': info() - }) + return self._get("Genres", { + 'ParentId': parent_id, + 'UserId': "{UserId}", + 'Fields': info() + }) def get_recommendation(self, parent_id=None, limit=20): - return self._get("Movies/Recommendations", { - 'ParentId': parent_id, - 'UserId': "{UserId}", - 'Fields': info(), - 'Limit': limit - }) + return self._get("Movies/Recommendations", { + 'ParentId': parent_id, + 'UserId': "{UserId}", + 'Fields': info(), + 'Limit': limit + }) def get_items_by_letter(self, parent_id=None, media=None, letter=None): - return self.user_items(params={ - 'ParentId': parent_id, - 'NameStartsWith': letter, - 'Fields': info(), - 'Recursive': True, - 'IncludeItemTypes': media - }) + return self.user_items(params={ + 'ParentId': parent_id, + 'NameStartsWith': letter, + 'Fields': info(), + 'Recursive': True, + 'IncludeItemTypes': media + }) def get_channels(self): - return self._get("LiveTv/Channels", { - 'UserId': "{UserId}", - 'EnableImages': True, - 'EnableUserData': True - }) + return self._get("LiveTv/Channels", { + 'UserId': "{UserId}", + 'EnableImages': True, + 'EnableUserData': True + }) def get_intros(self, item_id): - return self.user_items("/%s/Intros" % item_id) + return self.user_items("/%s/Intros" % item_id) def get_additional_parts(self, item_id): - return self.videos("/%s/AdditionalParts" % item_id) + return self.videos("/%s/AdditionalParts" % item_id) def delete_item(self, item_id): - return self.items("/%s" % item_id, "DELETE") + return self.items("/%s" % item_id, "DELETE") def get_local_trailers(self, item_id): - return self.user_items("/%s/LocalTrailers" % item_id) + return self.user_items("/%s/LocalTrailers" % item_id) def get_transcode_settings(self): - return self._get('System/Configuration/encoding') + return self._get('System/Configuration/encoding') def get_ancestors(self, item_id): - return self.items("/%s/Ancestors" % item_id, params={ - 'UserId': "{UserId}" - }) + return self.items("/%s/Ancestors" % item_id, params={ + 'UserId': "{UserId}" + }) def get_items_theme_video(self, parent_id): - return self.users("/Items", params={ - 'HasThemeVideo': True, - 'ParentId': parent_id - }) + return self.users("/Items", params={ + 'HasThemeVideo': True, + 'ParentId': parent_id + }) def get_themes(self, item_id): - return self.items("/%s/ThemeMedia" % item_id, params={ + return self.items("/%s/ThemeMedia" % item_id, params={ 'UserId': "{UserId}", 'InheritFromParent': True }) def get_items_theme_song(self, parent_id): - return self.users("/Items", params={ + return self.users("/Items", params={ 'HasThemeSong': True, 'ParentId': parent_id }) def get_plugins(self): - return self._get("Plugins") + return self._get("Plugins") def get_seasons(self, show_id): - return self.shows("/%s/Seasons" % show_id, params={ - 'UserId': "{UserId}", - 'EnableImages': True, - 'Fields': info() - }) + return self.shows("/%s/Seasons" % show_id, params={ + 'UserId': "{UserId}", + 'EnableImages': True, + 'Fields': info() + }) def get_date_modified(self, date, parent_id, media=None): - return self.users("/Items", params={ - 'ParentId': parent_id, - 'Recursive': False, - 'IsMissing': False, - 'IsVirtualUnaired': False, - 'IncludeItemTypes': media or None, - 'MinDateLastSaved': date, - 'Fields': info() - }) + return self.users("/Items", params={ + 'ParentId': parent_id, + 'Recursive': False, + 'IsMissing': False, + 'IsVirtualUnaired': False, + 'IncludeItemTypes': media or None, + 'MinDateLastSaved': date, + 'Fields': info() + }) def get_userdata_date_modified(self, date, parent_id, media=None): - return self.users("/Items", params={ - 'ParentId': parent_id, - 'Recursive': True, - 'IsMissing': False, - 'IsVirtualUnaired': False, - 'IncludeItemTypes': media or None, - 'MinDateLastSavedForUser': date, - 'Fields': info() - }) + return self.users("/Items", params={ + 'ParentId': parent_id, + 'Recursive': True, + 'IsMissing': False, + 'IsVirtualUnaired': False, + 'IncludeItemTypes': media or None, + 'MinDateLastSavedForUser': date, + 'Fields': info() + }) def refresh_item(self, item_id): - return self.items("/%s/Refresh" % item_id, "POST", json={ - 'Recursive': True, - 'ImageRefreshMode': "FullRefresh", - 'MetadataRefreshMode': "FullRefresh", - 'ReplaceAllImages': False, - 'ReplaceAllMetadata': True - }) + return self.items("/%s/Refresh" % item_id, "POST", json={ + 'Recursive': True, + 'ImageRefreshMode': "FullRefresh", + 'MetadataRefreshMode': "FullRefresh", + 'ReplaceAllImages': False, + 'ReplaceAllMetadata': True + }) def favorite(self, item_id, option=True): - return self.users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE") + return self.users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE") def get_system_info(self): - return self._get("System/Configuration") + return self._get("System/Configuration") def post_capabilities(self, data): - return self.sessions("/Capabilities/Full", "POST", json=data) + return self.sessions("/Capabilities/Full", "POST", json=data) def session_add_user(self, session_id, user_id, option=True): - return self.sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE") + return self.sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE") def session_playing(self, data): - return self.sessions("/Playing", "POST", json=data) + return self.sessions("/Playing", "POST", json=data) def session_progress(self, data): - return self.sessions("/Playing/Progress", "POST", json=data) + return self.sessions("/Playing/Progress", "POST", json=data) def session_stop(self, data): - return self.sessions("/Playing/Stopped", "POST", json=data) + return self.sessions("/Playing/Stopped", "POST", json=data) def item_played(self, item_id, watched): - return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE") + return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE") def get_sync_queue(self, date, filters=None): - return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={ - 'LastUpdateDT': date, - 'filter': filters or None - }) + return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={ + 'LastUpdateDT': date, + 'filter': filters or None + }) def get_server_time(self): - return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime") + return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime") def get_play_info(self, item_id, profile): - return self.items("/%s/PlaybackInfo" % item_id, "POST", json={ - 'UserId': "{UserId}", - 'DeviceProfile': profile, - 'AutoOpenLiveStream': True - }) + return self.items("/%s/PlaybackInfo" % item_id, "POST", json={ + 'UserId': "{UserId}", + 'DeviceProfile': profile, + 'AutoOpenLiveStream': True + }) def get_live_stream(self, item_id, play_id, token, profile): - return self._post("LiveStreams/Open", json={ - 'UserId': "{UserId}", - 'DeviceProfile': profile, - 'OpenToken': token, - 'PlaySessionId': play_id, - 'ItemId': item_id - }) + return self._post("LiveStreams/Open", json={ + 'UserId': "{UserId}", + 'DeviceProfile': profile, + 'OpenToken': token, + 'PlaySessionId': play_id, + 'ItemId': item_id + }) def close_live_stream(self, live_id): - return self._post("LiveStreams/Close", json={ - 'LiveStreamId': live_id - }) + return self._post("LiveStreams/Close", json={ + 'LiveStreamId': live_id + }) def close_transcode(self, device_id): - return self._delete("Videos/ActiveEncodings", params={ - 'DeviceId': device_id - }) + return self._delete("Videos/ActiveEncodings", params={ + 'DeviceId': device_id + }) def delete_item(self, item_id): - return self.items("/%s" % item_id, "DELETE") + return self.items("/%s" % item_id, "DELETE") diff --git a/resources/lib/library.py b/resources/lib/library.py index 2adab038..fefe62b1 100644 --- a/resources/lib/library.py +++ b/resources/lib/library.py @@ -123,9 +123,8 @@ class Library(threading.Thread): ''' Open the databases to test if the file exists. ''' - with Database('video') as kodidb: - with Database('music') as musicdb: - pass + with Database('video'), Database('music'): + pass @stop() def service(self): @@ -611,33 +610,29 @@ class UpdatedWorker(threading.Thread): threading.Thread.__init__(self) def run(self): + with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb: + while True: - with self.lock: - with self.database as kodidb: - with Database('jellyfin') as jellyfindb: + try: + item = self.queue.get(timeout=1) + except Queue.Empty: + break - while True: + obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']] - try: - item = self.queue.get(timeout=1) - except Queue.Empty: - break + try: + if obj(item) and self.notify: + self.notify_output.put((item['Type'], api.API(item).get_naming())) + except LibraryException as error: + if error.status == 'StopCalled': + break + except Exception as error: + LOG.exception(error) - obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']] + self.queue.task_done() - try: - if obj(item) and self.notify: - self.notify_output.put((item['Type'], api.API(item).get_naming())) - except LibraryException as error: - if error.status == 'StopCalled': - break - except Exception as error: - LOG.exception(error) - - self.queue.task_done() - - if window('jellyfin_should_stop.bool'): - break + if window('jellyfin_should_stop.bool'): + break LOG.info("--<[ q:updated/%s ]", id(self)) self.is_done = True @@ -656,31 +651,28 @@ class UserDataWorker(threading.Thread): def run(self): - with self.lock: - with self.database as kodidb: - with Database('jellyfin') as jellyfindb: + with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb: + while True: - while True: + try: + item = self.queue.get(timeout=1) + except Queue.Empty: + break - try: - item = self.queue.get(timeout=1) - except Queue.Empty: - break + obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData'] - obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData'] + try: + obj(item) + except LibraryException as error: + if error.status == 'StopCalled': + break + except Exception as error: + LOG.exception(error) - try: - obj(item) - except LibraryException as error: - if error.status == 'StopCalled': - break - except Exception as error: - LOG.exception(error) + self.queue.task_done() - self.queue.task_done() - - if window('jellyfin_should_stop.bool'): - break + if window('jellyfin_should_stop.bool'): + break LOG.info("--<[ q:userdata/%s ]", id(self)) self.is_done = True @@ -742,31 +734,28 @@ class RemovedWorker(threading.Thread): def run(self): - with self.lock: - with self.database as kodidb: - with Database('jellyfin') as jellyfindb: + with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb: + while True: - while True: + try: + item = self.queue.get(timeout=1) + except Queue.Empty: + break - try: - item = self.queue.get(timeout=1) - except Queue.Empty: - break + obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove'] - obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove'] + try: + obj(item['Id']) + except LibraryException as error: + if error.status == 'StopCalled': + break + except Exception as error: + LOG.exception(error) - try: - obj(item['Id']) - except LibraryException as error: - if error.status == 'StopCalled': - break - except Exception as error: - LOG.exception(error) + self.queue.task_done() - self.queue.task_done() - - if window('jellyfin_should_stop.bool'): - break + if window('jellyfin_should_stop.bool'): + break LOG.info("--<[ q:removed/%s ]", id(self)) self.is_done = True diff --git a/resources/lib/objects/kodi/artwork.py b/resources/lib/objects/kodi/artwork.py index 6e5412d7..c30ce155 100644 --- a/resources/lib/objects/kodi/artwork.py +++ b/resources/lib/objects/kodi/artwork.py @@ -165,7 +165,6 @@ class Artwork(object): from database import Database with Database('texture') as texturedb: - try: texturedb.cursor.execute(QUTEX.get_cache, (url,)) cached = texturedb.cursor.fetchone()[0] @@ -195,7 +194,6 @@ class GetArtworkWorker(threading.Thread): ''' with requests.Session() as s: while True: - try: url = self.queue.get(timeout=2) except Queue.Empty: