From 00765c0a12ac31214b6f7d05a05e5e275b9ada88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= <oddstr13@openshell.no> Date: Thu, 3 Oct 2019 04:14:54 +0200 Subject: [PATCH] Most flake8 warnings corrected --- resources/lib/client.py | 11 +- resources/lib/connect.py | 24 +- resources/lib/database/__init__.py | 24 +- resources/lib/database/jellyfin_db.py | 2 +- resources/lib/database/queries.py | 270 ++--- resources/lib/dialogs/context.py | 3 +- resources/lib/dialogs/loginmanual.py | 3 +- resources/lib/dialogs/resume.py | 6 +- resources/lib/dialogs/serverconnect.py | 3 +- resources/lib/dialogs/servermanual.py | 3 +- resources/lib/dialogs/usersconnect.py | 3 +- resources/lib/downloader.py | 13 +- resources/lib/entrypoint/context.py | 2 +- resources/lib/entrypoint/default.py | 63 +- resources/lib/entrypoint/service.py | 11 +- resources/lib/full_sync.py | 25 +- resources/lib/helper/api.py | 8 +- resources/lib/helper/exceptions.py | 3 +- resources/lib/helper/playutils.py | 39 +- resources/lib/helper/translate.py | 5 +- resources/lib/helper/utils.py | 48 +- resources/lib/helper/wrapper.py | 9 +- resources/lib/helper/xmls.py | 5 +- resources/lib/jellyfin/__init__.py | 6 +- resources/lib/jellyfin/client.py | 3 +- resources/lib/jellyfin/core/__init__.py | 1 - resources/lib/jellyfin/core/api.py | 12 +- resources/lib/jellyfin/core/configuration.py | 2 +- .../lib/jellyfin/core/connection_manager.py | 26 +- resources/lib/jellyfin/core/credentials.py | 3 +- resources/lib/jellyfin/core/exceptions.py | 3 +- resources/lib/jellyfin/core/http.py | 4 +- resources/lib/jellyfin/core/ws_client.py | 2 +- resources/lib/jellyfin/helpers/utils.py | 3 +- resources/lib/jellyfin/resources/__init__.py | 1 - resources/lib/jellyfin/resources/websocket.py | 53 +- resources/lib/library.py | 25 +- resources/lib/monitor.py | 8 +- resources/lib/objects/actions.py | 54 +- resources/lib/objects/kodi/artwork.py | 8 +- resources/lib/objects/kodi/kodi.py | 5 +- resources/lib/objects/kodi/movies.py | 5 +- resources/lib/objects/kodi/music.py | 14 +- resources/lib/objects/kodi/musicvideos.py | 5 +- resources/lib/objects/kodi/queries.py | 987 ++++++++---------- resources/lib/objects/kodi/queries_music.py | 446 ++++---- resources/lib/objects/kodi/queries_texture.py | 15 +- resources/lib/objects/kodi/tvshows.py | 13 +- resources/lib/objects/movies.py | 5 +- resources/lib/objects/music.py | 13 +- resources/lib/objects/musicvideos.py | 7 +- resources/lib/objects/obj.py | 6 +- resources/lib/objects/tvshows.py | 27 +- resources/lib/objects/utils.py | 2 +- resources/lib/player.py | 6 +- resources/lib/setup.py | 4 +- resources/lib/views.py | 43 +- resources/lib/webservice.py | 6 +- 58 files changed, 1144 insertions(+), 1262 deletions(-) diff --git a/resources/lib/client.py b/resources/lib/client.py index 44a4f041..3c4fa33c 100644 --- a/resources/lib/client.py +++ b/resources/lib/client.py @@ -15,19 +15,22 @@ from helper.utils import create_id ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## + def get_addon_name(): - + ''' Used for logging. ''' return xbmcaddon.Addon(addon_id()).getAddonInfo('name').upper() + def get_version(): return xbmcaddon.Addon(addon_id()).getAddonInfo('version') + def get_platform(): if xbmc.getCondVisibility('system.platform.osx'): @@ -53,6 +56,7 @@ def get_platform(): else: return "Unknown" + def get_device_name(): ''' Detect the device name. If deviceNameOpt, then @@ -68,6 +72,7 @@ def get_device_name(): return device_name + def get_device_id(reset=False): ''' Return the device_id if already loaded. @@ -105,6 +110,7 @@ def get_device_id(reset=False): return client_id + def reset_device_id(): window('jellyfin_deviceId', clear=True) @@ -112,6 +118,7 @@ def reset_device_id(): dialog("ok", heading="{jellyfin}", line1=_(33033)) xbmc.executebuiltin('RestartApp') + def get_info(): return { 'DeviceName': get_device_name(), diff --git a/resources/lib/connect.py b/resources/lib/connect.py index 6e4578db..86f490c1 100644 --- a/resources/lib/connect.py +++ b/resources/lib/connect.py @@ -20,7 +20,7 @@ from jellyfin.core.exceptions import HTTPException ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) XML_PATH = (xbmcaddon.Addon(addon_id()).getAddonInfo('path'), "default", "1080i") ################################################################################################## @@ -42,7 +42,7 @@ class Connect(object): if server_id is None and credentials['Servers']: credentials['Servers'] = [credentials['Servers'][0]] - + elif credentials['Servers']: for server in credentials['Servers']: @@ -88,7 +88,7 @@ class Connect(object): return client def register_client(self, credentials=None, options=None, server_id=None, server_selection=False): - + client = self.get_client(server_id) self.client = client self.connect_manager = client.auth @@ -102,7 +102,7 @@ class Connect(object): if state['State'] == CONNECTION_STATE['SignedIn']: client.callback_ws = event - if server_id is None: # Only assign for default server + if server_id is None: # Only assign for default server client.callback = event self.get_user(client) @@ -115,8 +115,7 @@ class Connect(object): return state['Credentials'] - elif (server_selection or state['State'] == CONNECTION_STATE['ServerSelection'] or - state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')): + elif (server_selection or state['State'] == CONNECTION_STATE['ServerSelection'] or state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')): self.select_servers(state) @@ -143,7 +142,6 @@ class Connect(object): return client.get_credentials() - def get_user(self, client): ''' Save user info. @@ -178,7 +176,8 @@ class Connect(object): LOG.debug("Adding manual server") try: self.manual_server() - except RuntimeError: pass + except RuntimeError: + pass else: raise RuntimeError("No server selected") @@ -237,14 +236,16 @@ class Connect(object): LOG.debug("User has password, present manual login") try: return self.login_manual(username) - except RuntimeError: pass + except RuntimeError: + pass else: return self.connect_manager.login(server, username) elif dialog.is_manual_login(): try: return self.login_manual() - except RuntimeError: pass + except RuntimeError: + pass else: raise RuntimeError("No user selected") @@ -267,7 +268,7 @@ class Connect(object): save_credentials(credentials) def login_manual(self, user=None, manager=None): - + ''' Return manual login user authenticated or raise error. ''' dialog = LoginManual("script-jellyfin-connect-login-manual.xml", *XML_PATH) @@ -294,4 +295,3 @@ class Connect(object): save_credentials(credentials) LOG.info("[ remove server ] %s", server_id) - diff --git a/resources/lib/database/__init__.py b/resources/lib/database/__init__.py index 19961f3b..5a93197d 100644 --- a/resources/lib/database/__init__.py +++ b/resources/lib/database/__init__.py @@ -18,7 +18,7 @@ from objects import obj ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -51,7 +51,7 @@ class Database(object): self.cursor = self.conn.cursor() if self.db_file in ('video', 'music', 'texture', 'jellyfin'): - self.conn.execute("PRAGMA journal_mode=WAL") # to avoid writing conflict with kodi + self.conn.execute("PRAGMA journal_mode=WAL") # to avoid writing conflict with kodi LOG.debug("--->[ database: %s ] %s", self.db_file, id(self.conn)) @@ -105,8 +105,7 @@ class Database(object): for file in reversed(files): - if (file.startswith(database) and not file.endswith('-wal') and - not file.endswith('-shm') and not file.endswith('db-journal')): + if (file.startswith(database) and not file.endswith('-wal') and not file.endswith('-shm') and not file.endswith('db-journal')): st = xbmcvfs.Stat(databases + file.decode('utf-8')) modified_int = st.st_mtime() @@ -147,7 +146,7 @@ class Database(object): loaded = self._get_database(databases[alt_file]) break - except KeyError: # No other db options + except KeyError: # No other db options loaded = None break @@ -172,7 +171,7 @@ class Database(object): ''' changes = self.conn.total_changes - if exc_type is not None: # errors raised + if exc_type is not None: # errors raised LOG.error("type: %s value: %s", exc_type, exc_val) if self.commit_close and changes: @@ -184,6 +183,7 @@ class Database(object): self.cursor.close() self.conn.close() + def jellyfin_tables(cursor): ''' Create the tables for the jellyfin database. @@ -205,6 +205,7 @@ def jellyfin_tables(cursor): LOG.info("Add missing column jellyfin_parent_id") cursor.execute("ALTER TABLE jellyfin ADD COLUMN jellyfin_parent_id 'TEXT'") + def reset(): ''' Reset both the jellyfin database and the kodi database. @@ -257,6 +258,7 @@ def reset(): dialog("ok", heading="{jellyfin}", line1=_(33088)) xbmc.executebuiltin('RestartApp') + def reset_kodi(): with Database() as videodb: @@ -281,6 +283,7 @@ def reset_kodi(): LOG.info("[ reset kodi ]") + def reset_jellyfin(): with Database('jellyfin') as jellyfindb: @@ -298,6 +301,7 @@ def reset_jellyfin(): LOG.info("[ reset jellyfin ]") + def reset_artwork(): ''' Remove all existing texture. @@ -325,6 +329,7 @@ def reset_artwork(): LOG.info("[ reset artwork ]") + def get_sync(): path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8') @@ -345,6 +350,7 @@ def get_sync(): return sync + def save_sync(sync): path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8') @@ -358,6 +364,7 @@ def save_sync(sync): data = json.dumps(sync, sort_keys=True, indent=4, ensure_ascii=False) outfile.write(unicode(data)) + def get_credentials(): path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8') @@ -383,19 +390,21 @@ def get_credentials(): return credentials + def save_credentials(credentials): credentials = credentials or {} path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8') if not xbmcvfs.exists(path): xbmcvfs.mkdirs(path) - try: + try: with open(os.path.join(path, 'data.json'), 'w', encoding='utf8') as outfile: data = json.dumps(credentials, sort_keys=True, indent=4, ensure_ascii=False) outfile.write(unicode(data)) except Exception as e: LOG.error("Failed to save credentials: {}".format(e)) + def get_item(kodi_id, media): ''' Get jellyfin item based on kodi id and media. @@ -409,4 +418,3 @@ def get_item(kodi_id, media): return return item - \ No newline at end of file diff --git a/resources/lib/database/jellyfin_db.py b/resources/lib/database/jellyfin_db.py index 195f5237..1b448f06 100644 --- a/resources/lib/database/jellyfin_db.py +++ b/resources/lib/database/jellyfin_db.py @@ -8,7 +8,7 @@ import queries as QU ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## diff --git a/resources/lib/database/queries.py b/resources/lib/database/queries.py index 5b9c4a7f..9008ed62 100644 --- a/resources/lib/database/queries.py +++ b/resources/lib/database/queries.py @@ -1,182 +1,142 @@ -get_item = """ SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, - jellyfin_type, media_folder, jellyfin_parent_id - FROM jellyfin - WHERE jellyfin_id = ? - """ -get_item_obj = [ "{Id}" - ] -get_item_series_obj = [ "{SeriesId}" - ] -get_item_song_obj = [ "{SongAlbumId}" - ] -get_item_id_by_parent = """ SELECT jellyfin_id, kodi_id - FROM jellyfin - WHERE parent_id = ? - AND media_type = ? - """ -get_item_id_by_parent_boxset_obj = [ "{SetId}","movie" - ] -get_item_by_parent = """ SELECT jellyfin_id, kodi_id, kodi_fileid - FROM jellyfin - WHERE parent_id = ? - AND media_type = ? +get_item = """ SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, + jellyfin_type, media_folder, jellyfin_parent_id + FROM jellyfin + WHERE jellyfin_id = ? + """ +get_item_obj = ["{Id}"] +get_item_series_obj = ["{SeriesId}"] +get_item_song_obj = ["{SongAlbumId}"] +get_item_id_by_parent = """ SELECT jellyfin_id, kodi_id + FROM jellyfin + WHERE parent_id = ? + AND media_type = ? """ -get_item_by_media_folder = """ SELECT jellyfin_id, jellyfin_type - FROM jellyfin - WHERE media_folder = ? +get_item_id_by_parent_boxset_obj = ["{SetId}", "movie"] +get_item_by_parent = """ SELECT jellyfin_id, kodi_id, kodi_fileid + FROM jellyfin + WHERE parent_id = ? + AND media_type = ? + """ +get_item_by_media_folder = """ SELECT jellyfin_id, jellyfin_type + FROM jellyfin + WHERE media_folder = ? """ -get_item_by_parent_movie_obj = [ "{KodiId}","movie" - ] -get_item_by_parent_tvshow_obj = [ "{ParentId}","tvshow" - ] -get_item_by_parent_season_obj = [ "{ParentId}","season" - ] -get_item_by_parent_episode_obj = [ "{ParentId}","episode" - ] -get_item_by_parent_album_obj = [ "{ParentId}","album" - ] -get_item_by_parent_song_obj = [ "{ParentId}","song" - ] -get_item_by_wild = """ SELECT kodi_id, media_type - FROM jellyfin - WHERE jellyfin_id LIKE ? - """ -get_item_by_wild_obj = [ "{Id}" - ] -get_item_by_kodi = """ SELECT jellyfin_id, parent_id, media_folder, jellyfin_type, checksum - FROM jellyfin - WHERE kodi_id = ? - AND media_type = ? - """ -get_checksum = """ SELECT jellyfin_id, checksum - FROM jellyfin - WHERE jellyfin_type = ? - """ -get_view_name = """ SELECT view_name - FROM view - WHERE view_id = ? +get_item_by_parent_movie_obj = ["{KodiId}", "movie"] +get_item_by_parent_tvshow_obj = ["{ParentId}", "tvshow"] +get_item_by_parent_season_obj = ["{ParentId}", "season"] +get_item_by_parent_episode_obj = ["{ParentId}", "episode"] +get_item_by_parent_album_obj = ["{ParentId}", "album"] +get_item_by_parent_song_obj = ["{ParentId}", "song"] +get_item_by_wild = """ SELECT kodi_id, media_type + FROM jellyfin + WHERE jellyfin_id LIKE ? """ -get_media_by_id = """ SELECT jellyfin_type - FROM jellyfin - WHERE jellyfin_id = ? +get_item_by_wild_obj = ["{Id}"] +get_item_by_kodi = """ SELECT jellyfin_id, parent_id, media_folder, jellyfin_type, checksum + FROM jellyfin + WHERE kodi_id = ? + AND media_type = ? """ -get_media_by_parent_id = """ SELECT jellyfin_id, jellyfin_type, kodi_id, kodi_fileid - FROM jellyfin - WHERE jellyfin_parent_id = ? - """ -get_view = """ SELECT view_name, media_type - FROM view +get_checksum = """ SELECT jellyfin_id, checksum + FROM jellyfin + WHERE jellyfin_type = ? + """ +get_view_name = """ SELECT view_name + FROM view WHERE view_id = ? """ -get_views = """ SELECT * +get_media_by_id = """ SELECT jellyfin_type + FROM jellyfin + WHERE jellyfin_id = ? + """ +get_media_by_parent_id = """ SELECT jellyfin_id, jellyfin_type, kodi_id, kodi_fileid + FROM jellyfin + WHERE jellyfin_parent_id = ? + """ +get_view = """ SELECT view_name, media_type + FROM view + WHERE view_id = ? + """ +get_views = """ SELECT * FROM view """ -get_views_by_media = """ SELECT * - FROM view - WHERE media_type = ? - """ -get_items_by_media = """ SELECT jellyfin_id - FROM jellyfin +get_views_by_media = """ SELECT * + FROM view WHERE media_type = ? """ -get_version = """ SELECT idVersion +get_items_by_media = """ SELECT jellyfin_id + FROM jellyfin + WHERE media_type = ? + """ +get_version = """ SELECT idVersion FROM version """ - -add_reference = """ INSERT OR REPLACE INTO jellyfin(jellyfin_id, kodi_id, kodi_fileid, kodi_pathid, jellyfin_type, - media_type, parent_id, checksum, media_folder, jellyfin_parent_id) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_reference_movie_obj = [ "{Id}","{MovieId}","{FileId}","{PathId}","Movie","movie", None,"{Checksum}","{LibraryId}", - "{JellyfinParentId}" - ] -add_reference_boxset_obj = [ "{Id}","{SetId}",None,None,"BoxSet","set",None,"{Checksum}",None,None - ] -add_reference_tvshow_obj = [ "{Id}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}", - "{JellyfinParentId}" - ] -add_reference_season_obj = [ "{Id}","{SeasonId}",None,None,"Season","season","{ShowId}",None,None,None - ] -add_reference_pool_obj = [ "{SeriesId}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}",None - ] -add_reference_episode_obj = [ "{Id}","{EpisodeId}","{FileId}","{PathId}","Episode","episode","{SeasonId}","{Checksum}", - None,"{JellyfinParentId}" - ] -add_reference_mvideo_obj = [ "{Id}","{MvideoId}","{FileId}","{PathId}","MusicVideo","musicvideo",None,"{Checksum}", - "{LibraryId}","{JellyfinParentId}" - ] -add_reference_artist_obj = [ "{Id}","{ArtistId}",None,None,"{ArtistType}","artist",None,"{Checksum}","{LibraryId}", - "{JellyfinParentId}" - ] -add_reference_album_obj = [ "{Id}","{AlbumId}",None,None,"MusicAlbum","album",None,"{Checksum}",None,"{JellyfinParentId}" - ] -add_reference_song_obj = [ "{Id}","{SongId}",None,"{PathId}","Audio","song","{AlbumId}","{Checksum}", - None,"{JellyfinParentId}" - ] -add_view = """ INSERT OR REPLACE INTO view(view_id, view_name, media_type) +add_reference = """ INSERT OR REPLACE INTO jellyfin(jellyfin_id, kodi_id, kodi_fileid, kodi_pathid, jellyfin_type, + media_type, parent_id, checksum, media_folder, jellyfin_parent_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_reference_movie_obj = ["{Id}", "{MovieId}", "{FileId}", "{PathId}", "Movie", "movie", None, "{Checksum}", "{LibraryId}", "{JellyfinParentId}"] +add_reference_boxset_obj = ["{Id}", "{SetId}", None, None, "BoxSet", "set", None, "{Checksum}", None, None] +add_reference_tvshow_obj = ["{Id}", "{ShowId}", None, "{PathId}", "Series", "tvshow", None, "{Checksum}", "{LibraryId}", "{JellyfinParentId}"] +add_reference_season_obj = ["{Id}", "{SeasonId}", None, None, "Season", "season", "{ShowId}", None, None, None] +add_reference_pool_obj = ["{SeriesId}", "{ShowId}", None, "{PathId}", "Series", "tvshow", None, "{Checksum}", "{LibraryId}", None] +add_reference_episode_obj = ["{Id}", "{EpisodeId}", "{FileId}", "{PathId}", "Episode", "episode", "{SeasonId}", "{Checksum}", None, "{JellyfinParentId}"] +add_reference_mvideo_obj = ["{Id}", "{MvideoId}", "{FileId}", "{PathId}", "MusicVideo", "musicvideo", None, "{Checksum}", "{LibraryId}", "{JellyfinParentId}"] +add_reference_artist_obj = ["{Id}", "{ArtistId}", None, None, "{ArtistType}", "artist", None, "{Checksum}", "{LibraryId}", "{JellyfinParentId}"] +add_reference_album_obj = ["{Id}", "{AlbumId}", None, None, "MusicAlbum", "album", None, "{Checksum}", None, "{JellyfinParentId}"] +add_reference_song_obj = ["{Id}", "{SongId}", None, "{PathId}", "Audio", "song", "{AlbumId}", "{Checksum}", None, "{JellyfinParentId}"] +add_view = """ INSERT OR REPLACE INTO view(view_id, view_name, media_type) VALUES (?, ?, ?) """ -add_version = """ INSERT OR REPLACE INTO version(idVersion) +add_version = """ INSERT OR REPLACE INTO version(idVersion) VALUES (?) """ -update_reference = """ UPDATE jellyfin - SET checksum = ? - WHERE jellyfin_id = ? - """ -update_reference_obj = [ "{Checksum}", "{Id}" - ] -update_parent = """ UPDATE jellyfin - SET parent_id = ? - WHERE jellyfin_id = ? - """ -update_parent_movie_obj = [ "{SetId}","{Id}" - ] -update_parent_episode_obj = [ "{SeasonId}","{Id}" - ] -update_parent_album_obj = [ "{ArtistId}","{AlbumId}"] +update_reference = """ UPDATE jellyfin + SET checksum = ? + WHERE jellyfin_id = ? + """ +update_reference_obj = ["{Checksum}", "{Id}"] +update_parent = """ UPDATE jellyfin + SET parent_id = ? + WHERE jellyfin_id = ? + """ +update_parent_movie_obj = ["{SetId}", "{Id}"] +update_parent_episode_obj = ["{SeasonId}", "{Id}"] +update_parent_album_obj = ["{ArtistId}", "{AlbumId}"] - -delete_item = """ DELETE FROM jellyfin - WHERE jellyfin_id = ? - """ -delete_item_obj = [ "{Id}" - ] -delete_item_by_parent = """ DELETE FROM jellyfin - WHERE parent_id = ? - AND media_type = ? - """ -delete_item_by_parent_tvshow_obj = [ "{ParentId}","tvshow" - ] -delete_item_by_parent_season_obj = [ "{ParentId}","season" - ] -delete_item_by_parent_episode_obj = [ "{ParentId}","episode" - ] -delete_item_by_parent_song_obj = [ "{ParentId}","song" - ] -delete_item_by_parent_artist_obj = [ "{ParentId}","artist" - ] -delete_item_by_parent_album_obj = [ "{KodiId}","album" - ] -delete_item_by_kodi = """ DELETE FROM jellyfin - WHERE kodi_id = ? - AND media_type = ? - """ -delete_item_by_wild = """ DELETE FROM jellyfin - WHERE jellyfin_id LIKE ? - """ -delete_view = """ DELETE FROM view +delete_item = """ DELETE FROM jellyfin + WHERE jellyfin_id = ? + """ +delete_item_obj = ["{Id}"] +delete_item_by_parent = """ DELETE FROM jellyfin + WHERE parent_id = ? + AND media_type = ? + """ +delete_item_by_parent_tvshow_obj = ["{ParentId}", "tvshow"] +delete_item_by_parent_season_obj = ["{ParentId}", "season"] +delete_item_by_parent_episode_obj = ["{ParentId}", "episode"] +delete_item_by_parent_song_obj = ["{ParentId}", "song"] +delete_item_by_parent_artist_obj = ["{ParentId}", "artist"] +delete_item_by_parent_album_obj = ["{KodiId}", "album"] +delete_item_by_kodi = """ DELETE FROM jellyfin + WHERE kodi_id = ? + AND media_type = ? + """ +delete_item_by_wild = """ DELETE FROM jellyfin + WHERE jellyfin_id LIKE ? + """ +delete_view = """ DELETE FROM view WHERE view_id = ? """ -delete_parent_boxset_obj = [ None, "{Movie}" - ] -delete_media_by_parent_id = """ DELETE FROM jellyfin - WHERE jellyfin_parent_id = ? +delete_parent_boxset_obj = [None, "{Movie}"] +delete_media_by_parent_id = """ DELETE FROM jellyfin + WHERE jellyfin_parent_id = ? """ -delete_version = """ DELETE FROM version +delete_version = """ DELETE FROM version """ diff --git a/resources/lib/dialogs/context.py b/resources/lib/dialogs/context.py index 9d1c2c2e..d5371167 100644 --- a/resources/lib/dialogs/context.py +++ b/resources/lib/dialogs/context.py @@ -12,7 +12,7 @@ from helper import window, addon_id ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -29,7 +29,6 @@ class ContextMenu(xbmcgui.WindowXMLDialog): _options = [] selected_option = None - def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) diff --git a/resources/lib/dialogs/loginmanual.py b/resources/lib/dialogs/loginmanual.py index 6256861a..40416c4f 100644 --- a/resources/lib/dialogs/loginmanual.py +++ b/resources/lib/dialogs/loginmanual.py @@ -12,7 +12,7 @@ from helper import _, addon_id ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -31,7 +31,6 @@ class LoginManual(xbmcgui.WindowXMLDialog): error = None username = None - def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) diff --git a/resources/lib/dialogs/resume.py b/resources/lib/dialogs/resume.py index aeb0397f..c4247b10 100644 --- a/resources/lib/dialogs/resume.py +++ b/resources/lib/dialogs/resume.py @@ -10,7 +10,7 @@ import xbmcaddon ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -43,7 +43,7 @@ class ResumeDialog(xbmcgui.WindowXMLDialog): self.getControl(START_BEGINNING).setLabel(xbmc.getLocalizedString(12021)) def onAction(self, action): - + if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU): self.close() @@ -52,7 +52,7 @@ class ResumeDialog(xbmcgui.WindowXMLDialog): if controlID == RESUME: self.selected_option = 1 self.close() - + if controlID == START_BEGINNING: self.selected_option = 0 self.close() diff --git a/resources/lib/dialogs/serverconnect.py b/resources/lib/dialogs/serverconnect.py index 90929d4f..349280b5 100644 --- a/resources/lib/dialogs/serverconnect.py +++ b/resources/lib/dialogs/serverconnect.py @@ -12,7 +12,7 @@ from jellyfin.core.connection_manager import CONNECTION_STATE ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -38,7 +38,6 @@ class ServerConnect(xbmcgui.WindowXMLDialog): _connect_login = False _manual_server = False - def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) diff --git a/resources/lib/dialogs/servermanual.py b/resources/lib/dialogs/servermanual.py index 66d0340c..30e63645 100644 --- a/resources/lib/dialogs/servermanual.py +++ b/resources/lib/dialogs/servermanual.py @@ -13,7 +13,7 @@ from jellyfin.core.connection_manager import CONNECTION_STATE ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -34,7 +34,6 @@ class ServerManual(xbmcgui.WindowXMLDialog): _server = None error = None - def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) diff --git a/resources/lib/dialogs/usersconnect.py b/resources/lib/dialogs/usersconnect.py index eaebfdab..ce441ccd 100644 --- a/resources/lib/dialogs/usersconnect.py +++ b/resources/lib/dialogs/usersconnect.py @@ -9,7 +9,7 @@ import xbmcgui ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ACTION_PARENT_DIR = 9 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 @@ -27,7 +27,6 @@ class UsersConnect(xbmcgui.WindowXMLDialog): _user = None _manual_login = False - def __init__(self, *args, **kwargs): self.kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2]) diff --git a/resources/lib/downloader.py b/resources/lib/downloader.py index 89fe6a47..a345ce00 100644 --- a/resources/lib/downloader.py +++ b/resources/lib/downloader.py @@ -15,7 +15,7 @@ from jellyfin.core.exceptions import HTTPException ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) LIMIT = min(int(settings('limitIndex') or 50), 50) ################################################################################################# @@ -35,13 +35,14 @@ def browse_info(): 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) @@ -61,10 +62,10 @@ def validate_view(library_id, item_id): ''' try: result = _get("Users/{UserId}/Items", { - 'ParentId': library_id, - 'Recursive': True, - 'Ids': item_id - }) + 'ParentId': library_id, + 'Recursive': True, + 'Ids': item_id + }) except Exception as error: LOG.exception(error) return False diff --git a/resources/lib/entrypoint/context.py b/resources/lib/entrypoint/context.py index a9ba6ad9..24310559 100644 --- a/resources/lib/entrypoint/context.py +++ b/resources/lib/entrypoint/context.py @@ -17,7 +17,7 @@ from objects import Actions ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) XML_PATH = (xbmcaddon.Addon('plugin.video.jellyfin').getAddonInfo('path'), "default", "1080i") OPTIONS = { 'Refresh': _(30410), diff --git a/resources/lib/entrypoint/default.py b/resources/lib/entrypoint/default.py index 16a53618..32003191 100644 --- a/resources/lib/entrypoint/default.py +++ b/resources/lib/entrypoint/default.py @@ -8,7 +8,6 @@ import sys import urlparse import urllib import os -import sys import xbmc import xbmcvfs @@ -24,14 +23,13 @@ from helper import _, event, settings, window, dialog, api, JSONRPC ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# class Events(object): - def __init__(self): ''' Parse the parameters. Reroute to our service.py @@ -65,7 +63,7 @@ class Events(object): jellyfin_id = params.get('id') get_video_extras(jellyfin_id, jellyfin_path, server) - elif mode =='play': + elif mode == 'play': item = TheVoid('GetItem', {'Id': params['id'], 'ServerId': server}).get() Actions(server).play(item, params.get('dbid'), params.get('transcode') == 'true', playlist=params.get('playlist') == 'true') @@ -180,7 +178,6 @@ def listing(): else: directory(server['Name'], "plugin://plugin.video.jellyfin/?mode=browse&server=%s" % server['Id'], context=context) - directory(_(33194), "plugin://plugin.video.jellyfin/?mode=managelibs", True) directory(_(33134), "plugin://plugin.video.jellyfin/?mode=addserver", False) directory(_(33054), "plugin://plugin.video.jellyfin/?mode=adduser", False) @@ -194,6 +191,7 @@ def listing(): xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1])) + def directory(label, path, folder=True, artwork=None, fanart=None, context=None): ''' Add directory listitem. context should be a list of tuples [(label, action)*] @@ -207,6 +205,7 @@ def directory(label, path, folder=True, artwork=None, fanart=None, context=None) return li + def dir_listitem(label, path, artwork=None, fanart=None): ''' Gets the icon paths for default node listings @@ -218,6 +217,7 @@ def dir_listitem(label, path, artwork=None, fanart=None): return li + def manage_libraries(): directory(_(33098), "plugin://plugin.video.jellyfin/?mode=refreshboxsets", False) @@ -230,6 +230,7 @@ def manage_libraries(): xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1])) + def browse(media, view_id=None, folder=None, server_id=None): ''' Browse content dynamically. @@ -274,7 +275,6 @@ def browse(media, view_id=None, folder=None, server_id=None): elif media == 'music': content_type = "artists" - if folder == 'recentlyadded': listing = TheVoid('RecentlyAdded', {'Id': view_id, 'ServerId': server_id}).get() elif folder == 'genres': @@ -316,7 +316,6 @@ def browse(media, view_id=None, folder=None, server_id=None): else: listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': False}).get() - if listing: actions = Actions(server_id) @@ -339,7 +338,7 @@ def browse(media, view_id=None, folder=None, server_id=None): 'folder': item['Id'], 'server': server_id } - path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) + path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) context = [] if item['Type'] in ('Series', 'Season', 'Playlist'): @@ -362,7 +361,7 @@ def browse(media, view_id=None, folder=None, server_id=None): 'folder': 'genres-%s' % item['Id'], 'server': server_id } - path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) + path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) list_li.append((path, li, True)) else: @@ -396,6 +395,7 @@ def browse(media, view_id=None, folder=None, server_id=None): xbmcplugin.setContent(int(sys.argv[1]), content_type) xbmcplugin.endOfDirectory(int(sys.argv[1])) + def browse_subfolders(media, view_id, server_id=None): ''' Display submenus for jellyfin views. @@ -415,12 +415,13 @@ def browse_subfolders(media, view_id, server_id=None): 'folder': view_id if node[0] == 'all' else node[0], 'server': server_id } - path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) + path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) directory(node[1] or view['Name'], path) xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1])) + def browse_letters(media, view_id, server_id=None): ''' Display letters as options. @@ -439,12 +440,13 @@ def browse_letters(media, view_id, server_id=None): 'folder': 'firstletter-%s' % node, 'server': server_id } - path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) + path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params)) directory(node, path) xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1])) + def get_folder_type(item, content_type=None): media = item['Type'] @@ -480,6 +482,7 @@ def get_media_type(media): elif media == 'music': return "MusicArtist,MusicAlbum,Audio" + def get_fanart(item_id, path, server_id=None): ''' Get extra fanart for listitems. This is called by skinhelper. @@ -524,6 +527,7 @@ def get_fanart(item_id, path, server_id=None): xbmcplugin.addDirectoryItems(int(sys.argv[1]), list_li, len(list_li)) xbmcplugin.endOfDirectory(int(sys.argv[1])) + def get_video_extras(item_id, path, server_id=None): ''' Returns the video files for the item as plugin listing, can be used @@ -565,6 +569,7 @@ def get_video_extras(item_id, path, server_id=None): #xbmcplugin.endOfDirectory(int(sys.argv[1])) """ + def get_next_episodes(item_id, limit): ''' Only for synced content. @@ -578,14 +583,14 @@ def get_next_episodes(item_id, limit): return result = JSONRPC('VideoLibrary.GetTVShows').execute({ - 'sort': {'order': "descending", 'method': "lastplayed"}, - 'filter': { - 'and': [ - {'operator': "true", 'field': "inprogress", 'value': ""}, - {'operator': "is", 'field': "tag", 'value': "%s" % library} - ]}, - 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] - }) + 'sort': {'order': "descending", 'method': "lastplayed"}, + 'filter': { + 'and': [ + {'operator': "true", 'field': "inprogress", 'value': ""}, + {'operator': "is", 'field': "tag", 'value': "%s" % library} + ]}, + 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] + }) try: items = result['result']['tvshows'] @@ -603,7 +608,7 @@ def get_next_episodes(item_id, limit): 'and': [ {'operator': "lessthan", 'field': "playcount", 'value': "1"}, {'operator': "greaterthan", 'field': "season", 'value': "0"} - ]}, + ]}, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", @@ -645,6 +650,7 @@ def get_next_episodes(item_id, limit): xbmcplugin.setContent(int(sys.argv[1]), 'episodes') xbmcplugin.endOfDirectory(int(sys.argv[1])) + def create_listitem(item): ''' Listitem based on jsonrpc items. @@ -656,7 +662,7 @@ def create_listitem(item): metadata = { 'Title': title, - 'duration': str(item['runtime']/60), + 'duration': str(item['runtime'] / 60), 'Plot': item['plot'], 'Playcount': item['playcount'] } @@ -688,7 +694,7 @@ def create_listitem(item): metadata['Premiered'] = item['firstaired'] if "rating" in item: - metadata['Rating'] = str(round(float(item['rating']),1)) + metadata['Rating'] = str(round(float(item['rating']), 1)) if "director" in item: metadata['Director'] = " / ".join(item['director']) @@ -711,10 +717,10 @@ def create_listitem(item): li.setProperty('resumetime', str(item['resume']['position'])) li.setProperty('totaltime', str(item['resume']['total'])) li.setArt(item['art']) - li.setThumbnailImage(item['art'].get('thumb','')) + li.setThumbnailImage(item['art'].get('thumb', '')) li.setIconImage('DefaultTVShows.png') li.setProperty('dbid', str(item['episodeid'])) - li.setProperty('fanart_image', item['art'].get('tvshow.fanart','')) + li.setProperty('fanart_image', item['art'].get('tvshow.fanart', '')) for key, value in item['streamdetails'].iteritems(): for stream in value: @@ -722,6 +728,7 @@ def create_listitem(item): return li + def add_user(): ''' Add or remove users from the default server session. @@ -738,7 +745,7 @@ def add_user(): if result < 0: return - if not result: # Add user + if not result: # Add user eligible = [x for x in users if x['Id'] not in [current_user['UserId'] for current_user in current]] resp = dialog("select", _(33064), [x['Name'] for x in eligible]) @@ -747,7 +754,7 @@ def add_user(): user = eligible[resp] event('AddUser', {'Id': user['Id'], 'Add': True}) - else: # Remove user + else: # Remove user resp = dialog("select", _(33064), [x['UserName'] for x in current]) if resp < 0: @@ -756,6 +763,7 @@ def add_user(): user = current[resp] event('AddUser', {'Id': user['UserId'], 'Add': False}) + def get_themes(): ''' Add theme media locally, via strm. This is only for tv tunes. @@ -786,7 +794,6 @@ def get_themes(): all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views() views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')] - items = {} server = TheVoid('GetServerAddress', {'ServerId': None}).get() token = TheVoid('GetToken', {'ServerId': None}).get() @@ -829,6 +836,7 @@ def get_themes(): dialog("notification", heading="{jellyfin}", message=_(33153), icon="{jellyfin}", time=1000, sound=False) + def delete_item(): ''' Delete keymap action. @@ -837,6 +845,7 @@ def delete_item(): context.Context(delete=True) + def backup(): ''' Jellyfin backup. diff --git a/resources/lib/entrypoint/service.py b/resources/lib/entrypoint/service.py index 7dab8260..1a0ef2bd 100644 --- a/resources/lib/entrypoint/service.py +++ b/resources/lib/entrypoint/service.py @@ -2,7 +2,7 @@ ################################################################################################# -import _strptime # Workaround for threads using datetime: _striptime is locked +import _strptime # Workaround for threads using datetime: _striptime is locked import json import logging import sys @@ -24,7 +24,7 @@ from database import Database, jellyfin_db, reset ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -38,7 +38,6 @@ class Service(xbmc.Monitor): warn = True settings = {'last_progress': datetime.today(), 'last_progress_report': datetime.today()} - def __init__(self): window('jellyfin_should_stop', clear=True) @@ -209,7 +208,7 @@ class Service(xbmc.Monitor): users = [user for user in (settings('additionalUsers') or "").decode('utf-8').split(',') if user] users.insert(0, settings('username').decode('utf-8')) dialog("notification", heading="{jellyfin}", message="%s %s" % (_(33000), ", ".join(users)), - icon="{jellyfin}", time=1500, sound=False) + icon="{jellyfin}", time=1500, sound=False) if self.library_thread is None: @@ -352,7 +351,7 @@ class Service(xbmc.Monitor): return LOG.info("--<[ sleep ]") - xbmc.sleep(10000)# Allow network to wake up + xbmc.sleep(10000) # Allow network to wake up self.monitor.sleep = False window('jellyfin_should_stop', clear=True) @@ -444,7 +443,7 @@ class Service(xbmc.Monitor): LOG.info("---<[ EXITING ]") window('jellyfin_should_stop.bool', True) - properties = [ # TODO: review + properties = [ # TODO: review "jellyfin_state", "jellyfin_serverStatus", "jellyfin_currUser", "jellyfin_play", "jellyfin_online", "jellyfin.connected", "jellyfin.resume", "jellyfin_startup", diff --git a/resources/lib/full_sync.py b/resources/lib/full_sync.py index 08cc5b49..bb49e5b1 100644 --- a/resources/lib/full_sync.py +++ b/resources/lib/full_sync.py @@ -19,7 +19,7 @@ from views import Views ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -36,7 +36,6 @@ class FullSync(object): running = False screensaver = None - def __init__(self, library, server): ''' You can call all big syncing methods here. @@ -69,7 +68,6 @@ class FullSync(object): return self - def libraries(self, library_id=None, update=False): ''' Map the syncing process and start the sync. Ensure only one sync is running. @@ -179,7 +177,6 @@ class FullSync(object): return [libraries[x - 1] for x in selection] - def start(self): ''' Main sync process. @@ -278,7 +275,7 @@ class FullSync(object): for index, movie in enumerate(items['Items']): - dialog.update(int((float(start_index + index) / float(items['TotalRecordCount']))*100), + dialog.update(int((float(start_index + index) / float(items['TotalRecordCount'])) * 100), heading="%s: %s" % (_('addon_name'), library['Name']), message=movie['Name']) obj.movie(movie, library=library) @@ -318,11 +315,11 @@ class FullSync(object): for index, show in enumerate(items['Items']): - percent = int((float(start_index + index) / float(items['TotalRecordCount']))*100) + percent = int((float(start_index + index) / float(items['TotalRecordCount'])) * 100) message = show['Name'] dialog.update(percent, heading="%s: %s" % (_('addon_name'), library['Name']), message=message) - if obj.tvshow(show, library=library) != False: + if obj.tvshow(show, library=library): for episodes in server.get_episode_by_show(show['Id']): for episode in episodes['Items']: @@ -368,7 +365,7 @@ class FullSync(object): for index, mvideo in enumerate(items['Items']): - dialog.update(int((float(start_index + index) / float(items['TotalRecordCount']))*100), + dialog.update(int((float(start_index + index) / float(items['TotalRecordCount'])) * 100), heading="%s: %s" % (_('addon_name'), library['Name']), message=mvideo['Name']) obj.musicvideo(mvideo, library=library) @@ -408,7 +405,7 @@ class FullSync(object): for index, artist in enumerate(items['Items']): - percent = int((float(start_index + index) / float(items['TotalRecordCount']))*100) + percent = int((float(start_index + index) / float(items['TotalRecordCount'])) * 100) message = artist['Name'] dialog.update(percent, heading="%s: %s" % (_('addon_name'), library['Name']), message=message) obj.artist(artist, library=library) @@ -431,7 +428,6 @@ class FullSync(object): dialog.update(percent, message="%s/%s" % (message, song['Name'])) obj.song(song) - if self.update_library: self.music_compare(library, obj, jellyfindb) @@ -470,7 +466,7 @@ class FullSync(object): for index, boxset in enumerate(items['Items']): - dialog.update(int((float(start_index + index) / float(items['TotalRecordCount']))*100), + dialog.update(int((float(start_index + index) / float(items['TotalRecordCount'])) * 100), heading="%s: %s" % (_('addon_name'), _('boxsets')), message=boxset['Name']) obj.boxset(boxset) @@ -524,7 +520,7 @@ class FullSync(object): for item in movies: obj(item[0]) - dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0])) + dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 obj = TVShows(self.server, jellyfindb, kodidb, direct_path).remove @@ -532,7 +528,7 @@ class FullSync(object): for item in tvshows: obj(item[0]) - dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0])) + dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 else: # from mcarlton: I'm not sure what triggers this. @@ -547,7 +543,7 @@ class FullSync(object): for item in items: obj(item[0]) - dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0])) + dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 self.sync = get_sync() @@ -560,7 +556,6 @@ class FullSync(object): save_sync(self.sync) - def __exit__(self, exc_type, exc_val, exc_tb): ''' Exiting sync diff --git a/resources/lib/helper/api.py b/resources/lib/helper/api.py index 068870a6..9fa7a841 100644 --- a/resources/lib/helper/api.py +++ b/resources/lib/helper/api.py @@ -8,14 +8,14 @@ from . import settings ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## class API(object): def __init__(self, item, server=None): - + ''' Get item information in special cases. server is the server address, provide if your functions requires it. ''' @@ -225,7 +225,7 @@ class API(object): return path def get_user_artwork(self, user_id): - + ''' Get jellyfin user profile picture. ''' return "%s/emby/Users/%s/Images/Primary?Format=original" % (self.server, user_id) @@ -286,7 +286,7 @@ class API(object): if obj.get('SeriesTag'): all_artwork['Series.Primary'] = self.get_artwork(obj['SeriesId'], "Primary", obj['SeriesTag'], query) - + if not all_artwork['Primary']: all_artwork['Primary'] = all_artwork['Series.Primary'] diff --git a/resources/lib/helper/exceptions.py b/resources/lib/helper/exceptions.py index 6e2e747e..c2ed4685 100644 --- a/resources/lib/helper/exceptions.py +++ b/resources/lib/helper/exceptions.py @@ -2,9 +2,8 @@ ################################################################################################# + class LibraryException(Exception): # Jellyfin library sync exception def __init__(self, status): self.status = status - - diff --git a/resources/lib/helper/playutils.py b/resources/lib/helper/playutils.py index 68899ddf..2fc04417 100644 --- a/resources/lib/helper/playutils.py +++ b/resources/lib/helper/playutils.py @@ -20,7 +20,7 @@ from downloader import TheVoid ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -52,8 +52,8 @@ def set_properties(item, method, server_id=None): window('jellyfin_play.json', current) -class PlayUtils(object): +class PlayUtils(object): def __init__(self, item, force_transcode=False, server_id=None, server=None, token=None): @@ -236,7 +236,7 @@ class PlayUtils(object): def transcode(self, source, audio=None, subtitle=None): - if not 'TranscodingUrl' in source: + if 'TranscodingUrl' not in source: raise Exception("use get_sources to get transcoding url") self.info['Method'] = "Transcode" @@ -248,7 +248,7 @@ class PlayUtils(object): url_parsed = params.split('&') for i in url_parsed: - if 'AudioStreamIndex' in i or 'AudioBitrate' in i or 'SubtitleStreamIndex' in i: # handle manually + if 'AudioStreamIndex' in i or 'AudioBitrate' in i or 'SubtitleStreamIndex' in i: # handle manually url_parsed.remove(i) params = "%s%s" % ('&'.join(url_parsed), self.get_audio_subs(source, audio, subtitle)) @@ -275,13 +275,19 @@ class PlayUtils(object): self.info['Method'] = "DirectStream" if self.item['Type'] == "Audio": - self.info['Path'] = ("%s/emby/Audio/%s/stream.%s?static=true&api_key=%s" % - (self.info['ServerAddress'], self.item['Id'], - source.get('Container', "mp4").split(',')[0], - self.info['Token'])) + self.info['Path'] = "%s/emby/Audio/%s/stream.%s?static=true&api_key=%s" % ( + self.info['ServerAddress'], + self.item['Id'], + source.get('Container', "mp4").split(',')[0], + self.info['Token'] + ) else: - self.info['Path'] = ("%s/emby/Videos/%s/stream?static=true&MediaSourceId=%s&api_key=%s" % - (self.info['ServerAddress'], self.item['Id'], source['Id'], self.info['Token'])) + self.info['Path'] = "%s/emby/Videos/%s/stream?static=true&MediaSourceId=%s&api_key=%s" % ( + self.info['ServerAddress'], + self.item['Id'], + source['Id'], + self.info['Token'] + ) return self.info['Path'] @@ -495,7 +501,6 @@ class PlayUtils(object): listitem.setSubtitles(subs) self.item['PlaybackInfo']['Subtitles'] = mapping - @classmethod def download_external_subs(cls, src, filename): @@ -579,7 +584,7 @@ class PlayUtils(object): selection = list(audio_streams.keys()) resp = dialog("select", _(33013), selection) audio_selected = audio_streams[selection[resp]] if resp else source['DefaultAudioStreamIndex'] - else: # Only one choice + else: # Only one choice audio_selected = audio_streams[next(iter(audio_streams))] else: audio_selected = source['DefaultAudioStreamIndex'] @@ -628,7 +633,13 @@ class PlayUtils(object): if stream['IsTextSubtitleStream'] and 'DeliveryUrl' in stream and stream['DeliveryUrl'].lower().startswith('/videos'): url = "%s/emby%s" % (self.info['ServerAddress'], stream['DeliveryUrl']) else: - url = ("%s/emby/Videos/%s/%s/Subtitles/%s/Stream.%s?api_key=%s" % - (self.info['ServerAddress'], self.item['Id'], source['Id'], index, stream['Codec'], self.info['Token'])) + url = "%s/emby/Videos/%s/%s/Subtitles/%s/Stream.%s?api_key=%s" % ( + self.info['ServerAddress'], + self.item['Id'], + source['Id'], + index, + stream['Codec'], + self.info['Token'] + ) return url diff --git a/resources/lib/helper/translate.py b/resources/lib/helper/translate.py index 70c5e3cb..89f04b58 100644 --- a/resources/lib/helper/translate.py +++ b/resources/lib/helper/translate.py @@ -11,10 +11,11 @@ import xbmcaddon ################################################################################################## -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################## + def _(string): ''' Get add-on string. Returns in unicode. @@ -26,7 +27,7 @@ def _(string): if not result: result = xbmc.getLocalizedString(string) - + return result diff --git a/resources/lib/helper/utils.py b/resources/lib/helper/utils.py index 1f57e74b..562723a0 100644 --- a/resources/lib/helper/utils.py +++ b/resources/lib/helper/utils.py @@ -22,16 +22,19 @@ from dateutil import tz, parser ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# + def addon_id(): return "plugin.video.jellyfin" + def kodi_version(): return xbmc.getInfoLabel('System.BuildVersion')[:2] + def window(key, value=None, clear=False, window_id=10000): ''' Get or set window properties. @@ -65,6 +68,7 @@ def window(key, value=None, clear=False, window_id=10000): return result + def settings(setting, value=None): ''' Get or add add-on settings. @@ -87,9 +91,11 @@ def settings(setting, value=None): return result + def create_id(): return uuid4() + def compare_version(a, b): ''' -1 a is smaller @@ -107,6 +113,7 @@ def compare_version(a, b): return 0 + def find(dict, item): ''' Find value in dictionary. @@ -114,11 +121,12 @@ def find(dict, item): if item in dict: return dict[item] - for key,value in sorted(dict.iteritems(), key=lambda (k,v): (v,k)): + for key, value in sorted(dict.iteritems(), key=lambda (k, v): (v, k)): if re.match(key, item, re.I): return dict[key] + def event(method, data=None, sender=None, hexlify=False): ''' Data is a dictionary. @@ -134,13 +142,16 @@ def event(method, data=None, sender=None, hexlify=False): xbmc.executebuiltin('NotifyAll(%s, %s, %s)' % (sender, method, data)) LOG.debug("---[ event: %s/%s ] %s", sender, method, data) + def dialog(dialog_type, *args, **kwargs): d = xbmcgui.Dialog() if "icon" in kwargs: - kwargs['icon'] = kwargs['icon'].replace("{jellyfin}", - "special://home/addons/plugin.video.jellyfin/resources/icon.png") + kwargs['icon'] = kwargs['icon'].replace( + "{jellyfin}", + "special://home/addons/plugin.video.jellyfin/resources/icon.png" + ) if "heading" in kwargs: kwargs['heading'] = kwargs['heading'].replace("{jellyfin}", _('addon_name')) @@ -155,6 +166,7 @@ def dialog(dialog_type, *args, **kwargs): } return types[dialog_type](*args, **kwargs) + def should_stop(): ''' Checkpoint during the sync process. @@ -171,6 +183,7 @@ def should_stop(): return False + def get_screensaver(): ''' Get the current screensaver value. @@ -181,6 +194,7 @@ def get_screensaver(): except KeyError: return "" + def set_screensaver(value): ''' Toggle the screensaver @@ -192,6 +206,7 @@ def set_screensaver(value): result = JSONRPC('Settings.setSettingValue').execute(params) LOG.info("---[ screensaver/%s ] %s", value, result) + class JSONRPC(object): version = 1 @@ -221,6 +236,7 @@ class JSONRPC(object): self.params = params return json.loads(xbmc.executeJSONRPC(self._query())) + def validate(path): ''' Verify if path is accessible. @@ -241,6 +257,7 @@ def validate(path): return True + def values(item, keys): ''' Grab the values in the item for a list of keys {key},{key1}.... @@ -248,6 +265,7 @@ def values(item, keys): ''' return (item[key.replace('{', "").replace('}', "")] if type(key) == str and key.startswith('{') else key for key in keys) + def indent(elem, level=0): ''' Prettify xml docs. @@ -256,20 +274,21 @@ def indent(elem, level=0): i = "\n" + level * " " if len(elem): if not elem.text or not elem.text.strip(): - elem.text = i + " " + elem.text = i + " " if not elem.tail or not elem.tail.strip(): - elem.tail = i + elem.tail = i for elem in elem: - indent(elem, level + 1) + indent(elem, level + 1) if not elem.tail or not elem.tail.strip(): - elem.tail = i + elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): - elem.tail = i + elem.tail = i except Exception as error: LOG.exception(error) return + def write_xml(content, file): with open(file, 'w') as infile: @@ -332,6 +351,7 @@ def unzip(path, dest, folder=None): LOG.info("Unzipped %s", path) + def unzip_recursive(path, dirs, dest): for directory in dirs: @@ -348,6 +368,7 @@ def unzip_recursive(path, dirs, dest): for file in files: unzip_file(os.path.join(dirs_dir, file.decode('utf-8')), os.path.join(dest_dir, file.decode('utf-8'))) + def unzip_file(path, dest): ''' Unzip specific file. Path should start with zip:// @@ -355,6 +376,7 @@ def unzip_file(path, dest): xbmcvfs.copy(path, dest) LOG.debug("unzip: %s to %s", path, dest) + def get_zip_directory(path, folder): dirs, files = xbmcvfs.listdir(path) @@ -367,6 +389,7 @@ def get_zip_directory(path, folder): if result: return result + def copytree(path, dest): ''' Copy folder content from one to another. @@ -384,6 +407,7 @@ def copytree(path, dest): LOG.info("Copied %s", path) + def copy_recursive(path, dirs, dest): for directory in dirs: @@ -400,6 +424,7 @@ def copy_recursive(path, dirs, dest): for file in files: copy_file(os.path.join(dirs_dir, file.decode('utf-8')), os.path.join(dest_dir, file.decode('utf-8'))) + def copy_file(path, dest): ''' Copy specific file. @@ -410,6 +435,7 @@ def copy_file(path, dest): xbmcvfs.copy(path, dest) LOG.debug("copy: %s to %s", path, dest) + def normalize_string(text): ''' For theme media, do not modify unless modified in TV Tunes. @@ -431,11 +457,13 @@ def normalize_string(text): return text + def split_list(itemlist, size): ''' Split up list in pieces of size. Will generate a list of lists ''' - return [itemlist[i:i+size] for i in range(0, len(itemlist), size)] + return [itemlist[i:i + size] for i in range(0, len(itemlist), size)] + def convert_to_local(date): diff --git a/resources/lib/helper/wrapper.py b/resources/lib/helper/wrapper.py index b5a89976..16175654 100644 --- a/resources/lib/helper/wrapper.py +++ b/resources/lib/helper/wrapper.py @@ -11,10 +11,11 @@ from utils import should_stop ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# + def progress(message=None): ''' Will start and close the progress dialog. @@ -61,6 +62,7 @@ def catch(errors=(Exception,)): return wrapper return decorator + def silent_catch(errors=(Exception,)): ''' Wrapper to catch exceptions and ignore them @@ -76,6 +78,7 @@ def silent_catch(errors=(Exception,)): return wrapper return decorator + def stop(default=None): ''' Wrapper to catch exceptions and return using catch @@ -100,6 +103,7 @@ def stop(default=None): return wrapper return decorator + def jellyfin_item(): ''' Wrapper to retrieve the jellyfin_db item. @@ -113,6 +117,7 @@ def jellyfin_item(): return wrapper return decorator + def library_check(): ''' Wrapper to retrieve the library @@ -148,7 +153,7 @@ def library_check(): return view = {'Id': views[0], 'Name': views[1]} - else: # Grab the first music library + else: # Grab the first music library return else: for ancestor in ancestors: diff --git a/resources/lib/helper/xmls.py b/resources/lib/helper/xmls.py index 13215de2..e095c6d3 100644 --- a/resources/lib/helper/xmls.py +++ b/resources/lib/helper/xmls.py @@ -13,10 +13,11 @@ from . import _, indent, write_xml, dialog, settings ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# + def sources(): ''' Create master lock compatible sources. @@ -77,6 +78,7 @@ def sources(): indent(xml) write_xml(etree.tostring(xml, 'UTF-8'), file) + def tvtunes_nfo(path, urls): ''' Create tvtunes.nfo @@ -96,6 +98,7 @@ def tvtunes_nfo(path, urls): indent(xml) write_xml(etree.tostring(xml, 'UTF-8'), path) + def advanced_settings(): ''' Track the existence of <cleanonupdate>true</cleanonupdate> diff --git a/resources/lib/jellyfin/__init__.py b/resources/lib/jellyfin/__init__.py index 591f2ee7..e8da2b1a 100644 --- a/resources/lib/jellyfin/__init__.py +++ b/resources/lib/jellyfin/__init__.py @@ -9,21 +9,25 @@ from helpers import has_attribute ################################################################################################# + class NullHandler(logging.Handler): def emit(self, record): print(self.format(record)) + loghandler = NullHandler LOG = logging.getLogger('Jellyfin') ################################################################################################# + def config(level=logging.INFO): logger = logging.getLogger('Jellyfin') logger.addHandler(Jellyfin.loghandler()) logger.setLevel(level) + def ensure_client(): def decorator(func): @@ -109,7 +113,7 @@ class Jellyfin(object): @ensure_client() def __getattr__(self, name): return getattr(self.client[self.server_id], name) - + def construct(self): self.client[self.server_id] = JellyfinClient() diff --git a/resources/lib/jellyfin/client.py b/resources/lib/jellyfin/client.py index a2b6318a..7f03ff92 100644 --- a/resources/lib/jellyfin/client.py +++ b/resources/lib/jellyfin/client.py @@ -12,10 +12,11 @@ from core.connection_manager import ConnectionManager, CONNECTION_STATE ################################################################################################# -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################# + def callback(message, data): ''' Callback function should received message, data diff --git a/resources/lib/jellyfin/core/__init__.py b/resources/lib/jellyfin/core/__init__.py index 8b137891..e69de29b 100644 --- a/resources/lib/jellyfin/core/__init__.py +++ b/resources/lib/jellyfin/core/__init__.py @@ -1 +0,0 @@ - diff --git a/resources/lib/jellyfin/core/api.py b/resources/lib/jellyfin/core/api.py index ffb1fad4..4d417a8a 100644 --- a/resources/lib/jellyfin/core/api.py +++ b/resources/lib/jellyfin/core/api.py @@ -225,15 +225,15 @@ class API(object): def get_themes(self, item_id): return self.items("/%s/ThemeMedia" % item_id, params={ - 'UserId': "{UserId}", - 'InheritFromParent': True - }) + 'UserId': "{UserId}", + 'InheritFromParent': True + }) def get_items_theme_song(self, parent_id): return self.users("/Items", params={ - 'HasThemeSong': True, - 'ParentId': parent_id - }) + 'HasThemeSong': True, + 'ParentId': parent_id + }) def get_plugins(self): return self._get("Plugins") diff --git a/resources/lib/jellyfin/core/configuration.py b/resources/lib/jellyfin/core/configuration.py index 31587552..06e50088 100644 --- a/resources/lib/jellyfin/core/configuration.py +++ b/resources/lib/jellyfin/core/configuration.py @@ -12,7 +12,7 @@ import logging DEFAULT_HTTP_MAX_RETRIES = 3 DEFAULT_HTTP_TIMEOUT = 30 -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################# diff --git a/resources/lib/jellyfin/core/connection_manager.py b/resources/lib/jellyfin/core/connection_manager.py index 7496413c..8fde9b13 100644 --- a/resources/lib/jellyfin/core/connection_manager.py +++ b/resources/lib/jellyfin/core/connection_manager.py @@ -16,7 +16,7 @@ from http import HTTP ################################################################################################# -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) CONNECTION_STATE = { 'Unavailable': 0, 'ServerSelection': 1, @@ -31,6 +31,7 @@ CONNECTION_MODE = { ################################################################################################# + def get_server_address(server, mode): modes = { @@ -86,7 +87,7 @@ class ConnectionManager(object): credentials = self.credentials.get_credentials() found_servers = self._find_servers(self._server_discovery()) - if not found_servers and not credentials['Servers']: # back out right away, no point in continuing + if not found_servers and not credentials['Servers']: # back out right away, no point in continuing LOG.info("Found no servers") return list() @@ -178,7 +179,7 @@ class ConnectionManager(object): LOG.info("beginning connection tests") return self._test_next_connection_mode(tests, 0, server, options) - def get_server_address(self, server, mode): #TODO: De-duplicated (Duplicated from above when getting rid of shortcuts) + def get_server_address(self, server, mode): # TODO: De-duplicated (Duplicated from above when getting rid of shortcuts) modes = { CONNECTION_MODE['Local']: server.get('LocalAddress'), @@ -239,8 +240,10 @@ class ConnectionManager(object): request.pop('dataType') headers['X-Application'] = self._add_app_info() - headers['Content-type'] = request.get('contentType', - 'application/x-www-form-urlencoded; charset=UTF-8') + headers['Content-type'] = request.get( + 'contentType', + 'application/x-www-form-urlencoded; charset=UTF-8' + ) def _connect_to_servers(self, servers, options): @@ -379,7 +382,7 @@ class ConnectionManager(object): MESSAGE = "who is JellyfinServer?" sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.settimeout(1.0) # This controls the socket.timeout exception + sock.settimeout(1.0) # This controls the socket.timeout exception sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) @@ -399,7 +402,7 @@ class ConnectionManager(object): while True: try: - data, addr = sock.recvfrom(1024) # buffer size + data, addr = sock.recvfrom(1024) # buffer size servers.append(json.loads(data)) except socket.timeout: @@ -446,7 +449,7 @@ class ConnectionManager(object): 'Id': found_server['Id'], 'LocalAddress': server or found_server['Address'], 'Name': found_server['Name'] - } #TODO + } # TODO info['LastConnectionMode'] = CONNECTION_MODE['Manual'] if info.get('ManualAddress') else CONNECTION_MODE['Local'] servers.append(info) @@ -461,7 +464,7 @@ class ConnectionManager(object): # Determine the port, if any parts = info['Address'].split(':') if len(parts) > 1: - port_string = parts[len(parts)-1] + port_string = parts[len(parts) - 1] try: address += ":%s" % int(port_string) @@ -496,7 +499,7 @@ class ConnectionManager(object): def _after_connect_validated(self, server, credentials, system_info, connection_mode, verify_authentication, options): - if options.get('enableAutoLogin') == False: + if not options.get('enableAutoLogin'): self.config.data['auth.user_id'] = server.pop('UserId', None) self.config.data['auth.token'] = server.pop('AccessToken', None) @@ -581,7 +584,8 @@ class ConnectionManager(object): if server['Id'] == result['ServerId']: found_server = server break - else: return # No server found + else: + return # No server found if options.get('updateDateLastAccessed') is not False: found_server['DateLastAccessed'] = datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ') diff --git a/resources/lib/jellyfin/core/credentials.py b/resources/lib/jellyfin/core/credentials.py index ccd6a33d..ac81f3d9 100644 --- a/resources/lib/jellyfin/core/credentials.py +++ b/resources/lib/jellyfin/core/credentials.py @@ -10,10 +10,11 @@ from datetime import datetime ################################################################################################# -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################# + class Credentials(object): credentials = None diff --git a/resources/lib/jellyfin/core/exceptions.py b/resources/lib/jellyfin/core/exceptions.py index c2a93ff1..aea09675 100644 --- a/resources/lib/jellyfin/core/exceptions.py +++ b/resources/lib/jellyfin/core/exceptions.py @@ -2,10 +2,9 @@ ################################################################################################# + class HTTPException(Exception): # Jellyfin HTTP exception def __init__(self, status, message): self.status = status self.message = message - - diff --git a/resources/lib/jellyfin/core/http.py b/resources/lib/jellyfin/core/http.py index ba4ebeb0..5986eb13 100644 --- a/resources/lib/jellyfin/core/http.py +++ b/resources/lib/jellyfin/core/http.py @@ -11,7 +11,7 @@ from exceptions import HTTPException ################################################################################################# -LOG = logging.getLogger('Jellyfin.'+__name__) +LOG = logging.getLogger('Jellyfin.' + __name__) ################################################################################################# @@ -127,7 +127,7 @@ class HTTP(object): raise HTTPException("AccessRestricted", error) else: self.client.callback("Unauthorized", {'ServerId': self.config.data['auth.server-id']}) - self.client.auth.revoke_token() + self.client.auth.revoke_token() raise HTTPException("Unauthorized", error) diff --git a/resources/lib/jellyfin/core/ws_client.py b/resources/lib/jellyfin/core/ws_client.py index beeb4598..267427a6 100644 --- a/resources/lib/jellyfin/core/ws_client.py +++ b/resources/lib/jellyfin/core/ws_client.py @@ -13,7 +13,7 @@ from ..resources import websocket ################################################################################################## -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################## diff --git a/resources/lib/jellyfin/helpers/utils.py b/resources/lib/jellyfin/helpers/utils.py index 0bfa0bc1..62848188 100644 --- a/resources/lib/jellyfin/helpers/utils.py +++ b/resources/lib/jellyfin/helpers/utils.py @@ -7,9 +7,10 @@ from uuid import uuid4 ################################################################################################# -LOG = logging.getLogger('JELLYFIN.'+__name__) +LOG = logging.getLogger('JELLYFIN.' + __name__) ################################################################################################# + def generate_client_id(): return str("%012X" % uuid4()) diff --git a/resources/lib/jellyfin/resources/__init__.py b/resources/lib/jellyfin/resources/__init__.py index 8b137891..e69de29b 100644 --- a/resources/lib/jellyfin/resources/__init__.py +++ b/resources/lib/jellyfin/resources/__init__.py @@ -1 +0,0 @@ - diff --git a/resources/lib/jellyfin/resources/websocket.py b/resources/lib/jellyfin/resources/websocket.py index bf27ed69..925ca19f 100644 --- a/resources/lib/jellyfin/resources/websocket.py +++ b/resources/lib/jellyfin/resources/websocket.py @@ -43,8 +43,6 @@ import base64 import threading import time import logging -import traceback -import sys """ websocket python client. @@ -89,12 +87,14 @@ class WebSocketConnectionClosedException(WebSocketException): """ pass + class WebSocketTimeoutException(WebSocketException): """ WebSocketTimeoutException will be raised at socket timeout during read/write data. """ pass + default_timeout = None traceEnabled = False @@ -135,8 +135,10 @@ def _wrap_sni_socket(sock, sslopt, hostname): if sslopt.get('cert_reqs', ssl.CERT_NONE) != ssl.CERT_NONE: capath = ssl.get_default_verify_paths().capath - context.load_verify_locations(cafile=sslopt.get('ca_certs', None), - capath=sslopt.get('ca_cert_path', capath)) + context.load_verify_locations( + cafile=sslopt.get('ca_certs', None), + capath=sslopt.get('ca_cert_path', capath) + ) return context.wrap_socket( sock, @@ -217,9 +219,10 @@ def create_connection(url, timeout=None, **options): websock.connect(url, **options) return websock -_MAX_INTEGER = (1 << 32) -1 + +_MAX_INTEGER = (1 << 32) - 1 _AVAILABLE_KEY_CHARS = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1) -_MAX_CHAR_BYTE = (1<<8) -1 +_MAX_CHAR_BYTE = (1 << 8) - 1 # ref. Websocket gets an update, and it breaks stuff. # http://axod.blogspot.com/2010/06/websocket-gets-update-and-it-breaks.html @@ -233,7 +236,7 @@ def _create_sec_websocket_key(): _HEADERS_TO_CHECK = { "upgrade": "websocket", "connection": "upgrade", - } +} class ABNF(object): @@ -244,16 +247,16 @@ class ABNF(object): """ # operation code values. - OPCODE_CONT = 0x0 - OPCODE_TEXT = 0x1 + OPCODE_CONT = 0x0 + OPCODE_TEXT = 0x1 OPCODE_BINARY = 0x2 - OPCODE_CLOSE = 0x8 - OPCODE_PING = 0x9 - OPCODE_PONG = 0xa + OPCODE_CLOSE = 0x8 + OPCODE_PING = 0x9 + OPCODE_PONG = 0xa # available operation code value tuple OPCODES = (OPCODE_CONT, OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE, - OPCODE_PING, OPCODE_PONG) + OPCODE_PING, OPCODE_PONG) # opcode human readable string OPCODE_MAP = { @@ -263,10 +266,10 @@ class ABNF(object): OPCODE_CLOSE: "close", OPCODE_PING: "ping", OPCODE_PONG: "pong" - } + } # data length threashold. - LENGTH_7 = 0x7d + LENGTH_7 = 0x7d LENGTH_16 = 1 << 16 LENGTH_63 = 1 << 63 @@ -287,8 +290,8 @@ class ABNF(object): def __str__(self): return "fin=" + str(self.fin) \ - + " opcode=" + str(self.opcode) \ - + " data=" + str(self.data) + + " opcode=" + str(self.opcode) \ + + " data=" + str(self.data) @staticmethod def create_frame(data, opcode): @@ -318,9 +321,7 @@ class ABNF(object): if length >= ABNF.LENGTH_63: raise ValueError("data is too long") - frame_header = chr(self.fin << 7 - | self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4 - | self.opcode) + frame_header = chr(self.fin << 7 | self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4 | self.opcode) if length < ABNF.LENGTH_7: frame_header += chr(self.mask << 7 | length) elif length < ABNF.LENGTH_16: @@ -582,8 +583,7 @@ class WebSocket(object): if traceEnabled: logger.debug("send: " + repr(data)) while data: - l = self._send(data) - data = data[l:] + data = data[self._send(data):] return length def send_binary(self, payload): @@ -685,7 +685,6 @@ class WebSocket(object): self._frame_mask = None return ABNF(fin, rsv1, rsv2, rsv3, opcode, has_mask, payload) - def send_close(self, status=STATUS_NORMAL, reason=""): """ send close data to the server. @@ -709,7 +708,7 @@ class WebSocket(object): try: self.sock.shutdown(socket.SHUT_RDWR) - except: + except: # noqa: E722 pass ''' @@ -766,7 +765,6 @@ class WebSocket(object): raise WebSocketConnectionClosedException() return bytes - def _recv_strict(self, bufsize): shortage = bufsize - sum(len(x) for x in self._recv_buffer) while shortage > 0: @@ -781,7 +779,6 @@ class WebSocket(object): self._recv_buffer = [unified[bufsize:]] return unified[:bufsize] - def _recv_line(self): line = [] while True: @@ -844,7 +841,7 @@ class WebSocketApp(object): close websocket connection. """ self.keep_running = False - if(self.sock != None): + if self.sock is None: self.sock.close() def _send_ping(self, interval): @@ -890,7 +887,7 @@ class WebSocketApp(object): try: data = self.sock.recv() - if data is None or self.keep_running == False: + if data is None or not self.keep_running: break self._callback(self.on_message, data) diff --git a/resources/lib/library.py b/resources/lib/library.py index 6f9854ec..2b14fbf0 100644 --- a/resources/lib/library.py +++ b/resources/lib/library.py @@ -22,7 +22,7 @@ from jellyfin import Jellyfin ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) LIMIT = min(int(settings('limitIndex') or 50), 50) DTHREADS = int(settings('limitThreads') or 3) MEDIA = { @@ -41,7 +41,6 @@ MEDIA = { ################################################################################################## - class Library(threading.Thread): started = False @@ -52,7 +51,6 @@ class Library(threading.Thread): progress_updates = None total_updates = 0 - def __init__(self, monitor): self.media = {'Movies': Movies, 'TVShows': TVShows, 'MusicVideos': MusicVideos, 'Music': Music} @@ -159,11 +157,11 @@ class Library(threading.Thread): self.progress_updates = xbmcgui.DialogProgressBG() self.progress_updates.create(_('addon_name'), _(33178)) - self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates))*100), message="%s: %s" % (_(33178), queue_size)) + self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message="%s: %s" % (_(33178), queue_size)) elif queue_size: - self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates))*100), message="%s: %s" % (_(33178), queue_size)) + self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message="%s: %s" % (_(33178), queue_size)) else: - self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates))*100), message=_(33178)) + self.progress_updates.update(int((float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message=_(33178)) if not settings('dbSyncScreensaver.bool') and self.screensaver is None: @@ -171,8 +169,7 @@ class Library(threading.Thread): self.screensaver = get_screensaver() set_screensaver(value="") - if (self.pending_refresh and not self.download_threads and not self.writer_threads['updated'] and - not self.writer_threads['userdata'] and not self.writer_threads['removed']): + if (self.pending_refresh and not self.download_threads and not self.writer_threads['updated'] and not self.writer_threads['userdata'] and not self.writer_threads['removed']): self.pending_refresh = False self.save_last_sync() self.total_updates = 0 @@ -189,9 +186,9 @@ class Library(threading.Thread): set_screensaver(value=self.screensaver) self.screensaver = None - if xbmc.getCondVisibility('Container.Content(musicvideos)'): # Prevent cursor from moving + if xbmc.getCondVisibility('Container.Content(musicvideos)'): # Prevent cursor from moving xbmc.executebuiltin('Container.Refresh') - else: # Update widgets + else: # Update widgets xbmc.executebuiltin('UpdateLibrary(video)') if xbmc.getCondVisibility('Window.IsMedia'): @@ -313,7 +310,6 @@ class Library(threading.Thread): LOG.info("-->[ q:notify/%s ]", id(new_thread)) self.notify_threads.append(new_thread) - def startup(self): ''' Run at startup. @@ -491,7 +487,7 @@ class Library(threading.Thread): available = [x for x in sync['SortedViews'] if x not in whitelist] for library in available: - name, media = db.get_view(library) + name, media = db.get_view(library) if media in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'): libraries.append({'Id': library, 'Name': name}) @@ -546,7 +542,6 @@ class Library(threading.Thread): return True - def userdata(self, data): ''' Add item_id to userdata queue. @@ -654,6 +649,7 @@ class UpdatedWorker(threading.Thread): LOG.info("--<[ q:updated/%s ]", id(self)) self.is_done = True + class UserDataWorker(threading.Thread): is_done = False @@ -697,6 +693,7 @@ class UserDataWorker(threading.Thread): LOG.info("--<[ q:userdata/%s ]", id(self)) self.is_done = True + class SortWorker(threading.Thread): is_done = False @@ -742,6 +739,7 @@ class SortWorker(threading.Thread): LOG.info("--<[ q:sort/%s ]", id(self)) self.is_done = True + class RemovedWorker(threading.Thread): is_done = False @@ -789,6 +787,7 @@ class RemovedWorker(threading.Thread): LOG.info("--<[ q:removed/%s ]", id(self)) self.is_done = True + class NotifyWorker(threading.Thread): is_done = False diff --git a/resources/lib/monitor.py b/resources/lib/monitor.py index bacca814..31013b09 100644 --- a/resources/lib/monitor.py +++ b/resources/lib/monitor.py @@ -22,7 +22,7 @@ from webservice import WebService ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -84,7 +84,7 @@ class Monitor(xbmc.Monitor): Otherwise the next played item will be added the previous queue. ''' if method == "Player.OnStop": - xbmc.sleep(3000) # let's wait for the player so we don't clear the canceled playlist by mistake. + xbmc.sleep(3000) # let's wait for the player so we don't clear the canceled playlist by mistake. if xbmc.getCondVisibility("!Player.HasMedia + !Window.IsVisible(busydialog)"): @@ -144,7 +144,7 @@ class Monitor(xbmc.Monitor): self.void_responder(data, item) elif method == 'GetServerAddress': - + server_data = server.auth.get_server_info(server.auth.server_id) server_address = server.auth.get_server_address(server_data, server_data['LastConnectionMode']) self.void_responder(data, server_address) @@ -392,7 +392,7 @@ class Monitor(xbmc.Monitor): elif command == 'DisplayMessage': dialog("notification", heading=args['Header'], message=args['Text'], - icon="{jellyfin}", time=int(settings('displayMessage'))*1000) + icon="{jellyfin}", time=int(settings('displayMessage')) * 1000) elif command == 'SendString': JSONRPC('Input.SendText').execute({'text': args['String'], 'done': False}) diff --git a/resources/lib/objects/actions.py b/resources/lib/objects/actions.py index 34fda957..10997257 100644 --- a/resources/lib/objects/actions.py +++ b/resources/lib/objects/actions.py @@ -22,7 +22,7 @@ from utils import get_play_action ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -58,7 +58,7 @@ class Actions(object): play.set_external_subs(source, listitem) self.set_playlist(item, listitem, db_id, transcode) - index = max(kodi_playlist.getposition(), 0) + 1 # Can return -1 + index = max(kodi_playlist.getposition(), 0) + 1 # Can return -1 force_play = False self.stack[0][1].setPath(self.stack[0][0]) @@ -79,7 +79,8 @@ class Actions(object): index += 1 if force_play: - if len(sys.argv) > 1: xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, self.stack[0][1]) + if len(sys.argv) > 1: + xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, self.stack[0][1]) xbmc.Player().play(kodi_playlist, windowed=False) def set_playlist(self, item, listitem, db_id=None, transcode=False): @@ -177,7 +178,7 @@ class Actions(object): playlist = self.get_playlist(item) player = xbmc.Player() - #xbmc.executebuiltin("Playlist.Clear") # Clear playlist to remove the previous item from playlist position no.2 + # xbmc.executebuiltin("Playlist.Clear") # Clear playlist to remove the previous item from playlist position no.2 if clear: if player.isPlaying(): @@ -186,7 +187,7 @@ class Actions(object): xbmc.executebuiltin('ActivateWindow(busydialognocancel)') index = 0 else: - index = max(playlist.getposition(), 0) + 1 # Can return -1 + index = max(playlist.getposition(), 0) + 1 # Can return -1 listitem = xbmcgui.ListItem() LOG.info("[ playlist/%s ] %s", item['Id'], item['Name']) @@ -282,7 +283,7 @@ class Actions(object): ''' Set listitem for video content. That also include streams. ''' API = api.API(item, self.server) - is_video = obj['MediaType'] in ('Video', 'Audio') # audiobook + is_video = obj['MediaType'] in ('Video', 'Audio') # audiobook obj['Genres'] = " / ".join(obj['Genres'] or []) obj['Studios'] = [API.validate_studio(studio) for studio in (obj['Studios'] or [])] @@ -312,21 +313,21 @@ class Actions(object): if not intro and not obj['Type'] == 'Trailer': obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \ - or "special://home/addons/plugin.video.jellyfin/resources/icon.png" + or "special://home/addons/plugin.video.jellyfin/resources/icon.png" else: obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \ - or obj['Artwork']['Thumb'] \ - or (obj['Artwork']['Backdrop'][0] \ - if len(obj['Artwork']['Backdrop']) \ + or obj['Artwork']['Thumb'] \ + or (obj['Artwork']['Backdrop'][0] + if len(obj['Artwork']['Backdrop']) else "special://home/addons/plugin.video.jellyfin/resources/fanart.png") obj['Artwork']['Primary'] += "&KodiTrailer=true" \ - if obj['Type'] == 'Trailer' else "&KodiCinemaMode=true" + if obj['Type'] == 'Trailer' else "&KodiCinemaMode=true" obj['Artwork']['Backdrop'] = [obj['Artwork']['Primary']] self.set_artwork(obj['Artwork'], listitem, obj['Type']) if intro or obj['Type'] == 'Trailer': - listitem.setArt({'poster': ""}) # Clear the poster value for intros / trailers to prevent issues in skins + listitem.setArt({'poster': ""}) # Clear the poster value for intros / trailers to prevent issues in skins listitem.setIconImage('DefaultVideo.png') listitem.setThumbnailImage(obj['Artwork']['Primary']) @@ -442,9 +443,9 @@ class Actions(object): listitem.setProperty('IsPlayable', 'true') listitem.setProperty('IsFolder', 'false') - if obj['Resume'] and seektime != False: + if obj['Resume'] and seektime: listitem.setProperty('resumetime', str(obj['Resume'])) - listitem.setProperty('StartPercent', str(((obj['Resume']/obj['Runtime']) * 100) - 0.40)) + listitem.setProperty('StartPercent', str(((obj['Resume'] / obj['Runtime']) * 100) - 0.40)) else: listitem.setProperty('resumetime', '0') @@ -478,11 +479,11 @@ class Actions(object): obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount']) or 0 obj['Overlay'] = 7 if obj['Played'] else 6 obj['Artwork']['Primary'] = obj['Artwork']['Primary'] \ - or "special://home/addons/plugin.video.jellyfin/resources/icon.png" + or "special://home/addons/plugin.video.jellyfin/resources/icon.png" obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] \ - or "special://home/addons/plugin.video.jellyfin/resources/fanart.png" + or "special://home/addons/plugin.video.jellyfin/resources/fanart.png" obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] \ - or ["special://home/addons/plugin.video.jellyfin/resources/fanart.png"] + or ["special://home/addons/plugin.video.jellyfin/resources/fanart.png"] metadata = { 'title': obj['Title'], @@ -625,7 +626,7 @@ class Actions(object): 'clearlogo': "Logo", 'discart': "Disc", 'fanart': "Backdrop", - 'fanart_image': "Backdrop", # in case + 'fanart_image': "Backdrop", # in case 'thumb': "Primary" } else: @@ -671,9 +672,9 @@ class Actions(object): dialog.doModal() if dialog.is_selected(): - if not dialog.get_selected(): # Start from beginning selected. + if not dialog.get_selected(): # Start from beginning selected. return False - else: # User backed out + else: # User backed out LOG.info("User exited without a selection.") return @@ -688,9 +689,7 @@ class Actions(object): return False - if (not xbmc.getCondVisibility('Window.IsMedia') and - ((item['Type'] == 'Audio' and not xbmc.getCondVisibility('Integer.IsGreater(Playlist.Length(music),1)')) or - not xbmc.getCondVisibility('Integer.IsGreater(Playlist.Length(video),1)'))): + if (not xbmc.getCondVisibility('Window.IsMedia') and ((item['Type'] == 'Audio' and not xbmc.getCondVisibility('Integer.IsGreater(Playlist.Length(music),1)')) or not xbmc.getCondVisibility('Integer.IsGreater(Playlist.Length(video),1)'))): return True @@ -733,6 +732,7 @@ def on_update(data, server): window('jellyfin.skip.%s' % item[0], clear=True) + def on_play(data, server): ''' Setup progress for jellyfin playback. @@ -781,6 +781,7 @@ def on_play(data, server): item['PlaybackInfo'] = {'Path': file} playutils.set_properties(item, 'DirectStream' if settings('useDirectPaths') == '0' else 'DirectPlay') + def special_listener(): ''' Corner cases that needs to be listened to. @@ -790,12 +791,11 @@ def special_listener(): isPlaying = player.isPlaying() count = int(window('jellyfin.external_count') or 0) - if (not isPlaying and xbmc.getCondVisibility('Window.IsVisible(DialogContextMenu.xml)') and - xbmc.getInfoLabel('Control.GetLabel(1002)') == xbmc.getLocalizedString(12021)): + if (not isPlaying and xbmc.getCondVisibility('Window.IsVisible(DialogContextMenu.xml)') and xbmc.getInfoLabel('Control.GetLabel(1002)') == xbmc.getLocalizedString(12021)): control = int(xbmcgui.Window(10106).getFocusId()) - if control == 1002: # Start from beginning + if control == 1002: # Start from beginning LOG.info("Resume dialog: Start from beginning selected.") window('jellyfin.resume.bool', False) @@ -806,7 +806,7 @@ def special_listener(): elif isPlaying and not window('jellyfin.external_check'): time = player.getTime() - if time > 1: # Not external player. + if time > 1: # Not external player. window('jellyfin.external_check', value="true") window('jellyfin.external_count', value="0") diff --git a/resources/lib/objects/kodi/artwork.py b/resources/lib/objects/kodi/artwork.py index 5b7acc8d..f4bebd24 100644 --- a/resources/lib/objects/kodi/artwork.py +++ b/resources/lib/objects/kodi/artwork.py @@ -17,7 +17,7 @@ import requests ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -37,7 +37,6 @@ class Artwork(object): 'port': settings('webServerPort') } - def update(self, image_url, kodi_id, media, image): ''' Update artwork in the video database. @@ -210,7 +209,7 @@ class GetArtworkWorker(threading.Thread): prep = req.prepare() prep.url = "http://%s:%s/image/image://%s" % (self.kodi['host'], self.kodi['port'], url) s.send(prep, timeout=(0.01, 0.01)) - s.content # release the connection + s.content # release the connection except Exception as error: LOG.exception(error) @@ -220,8 +219,6 @@ class GetArtworkWorker(threading.Thread): break - - """ # -*- coding: utf-8 -*- @@ -381,4 +378,3 @@ class Artwork(object): count += 1 """ - diff --git a/resources/lib/objects/kodi/kodi.py b/resources/lib/objects/kodi/kodi.py index 845d3ff9..bee8db0b 100644 --- a/resources/lib/objects/kodi/kodi.py +++ b/resources/lib/objects/kodi/kodi.py @@ -12,14 +12,13 @@ from helper import values ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## class Kodi(object): - def __init__(self): self.artwork = artwork.Artwork(self.cursor) @@ -215,7 +214,7 @@ class Kodi(object): return self.add_studio(*args) def add_streams(self, file_id, streams, runtime): - + ''' First remove any existing entries Then re-add video, audio and subtitles. ''' diff --git a/resources/lib/objects/kodi/movies.py b/resources/lib/objects/kodi/movies.py index a01f7fe1..38fd9329 100644 --- a/resources/lib/objects/kodi/movies.py +++ b/resources/lib/objects/kodi/movies.py @@ -9,14 +9,13 @@ import queries as QU ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## class Movies(Kodi): - def __init__(self, cursor): self.cursor = cursor @@ -29,7 +28,7 @@ class Movies(Kodi): def create_entry_rating(self): self.cursor.execute(QU.create_rating) - + return self.cursor.fetchone()[0] + 1 def create_entry(self): diff --git a/resources/lib/objects/kodi/music.py b/resources/lib/objects/kodi/music.py index a036d46e..6b676b1d 100644 --- a/resources/lib/objects/kodi/music.py +++ b/resources/lib/objects/kodi/music.py @@ -9,7 +9,7 @@ from kodi import Kodi ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -34,17 +34,17 @@ class Music(Kodi): def create_entry_album(self): self.cursor.execute(QU.create_album) - + return self.cursor.fetchone()[0] + 1 def create_entry_song(self): self.cursor.execute(QU.create_song) - + return self.cursor.fetchone()[0] + 1 def create_entry_genre(self): self.cursor.execute(QU.create_genre) - + return self.cursor.fetchone()[0] + 1 def update_path(self, *args): @@ -212,7 +212,7 @@ class Music(Kodi): ''' Add genres, but delete current genres first. Album_genres was removed in kodi 18 ''' - if media == 'album' and self.version_id < 72 : + if media == 'album' and self.version_id < 72: self.cursor.execute(QU.delete_genres_album, (kodi_id,)) for genre in genres: @@ -258,11 +258,11 @@ class Music(Kodi): return self.cursor.fetchone()[0] - #current bug in Kodi 18 that will ask for a scan of music tags unless this is set without a lastscanned + # current bug in Kodi 18 that will ask for a scan of music tags unless this is set without a lastscanned def update_versiontagscan(self): if self.version_id < 72: return else: self.cursor.execute(QU.get_versiontagcount) if self.cursor.fetchone()[0] == 0: - self.cursor.execute(QU.update_versiontag, (self.version_id,)) \ No newline at end of file + self.cursor.execute(QU.update_versiontag, (self.version_id,)) diff --git a/resources/lib/objects/kodi/musicvideos.py b/resources/lib/objects/kodi/musicvideos.py index 5e8f7e54..764a79ba 100644 --- a/resources/lib/objects/kodi/musicvideos.py +++ b/resources/lib/objects/kodi/musicvideos.py @@ -9,14 +9,13 @@ from kodi import Kodi ################################################################################################## -log = logging.getLogger("JELLYFIN."+__name__) +log = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## class MusicVideos(Kodi): - def __init__(self, cursor): self.cursor = cursor @@ -31,7 +30,7 @@ class MusicVideos(Kodi): try: self.cursor.execute(QU.get_musicvideo, args) - + return self.cursor.fetchone()[0] except TypeError: return diff --git a/resources/lib/objects/kodi/queries.py b/resources/lib/objects/kodi/queries.py index 2678cd75..c8b7357d 100644 --- a/resources/lib/objects/kodi/queries.py +++ b/resources/lib/objects/kodi/queries.py @@ -3,548 +3,467 @@ Some functions require additional information, therefore obj do not always reflect the Kodi database query values. ''' -create_path = """ SELECT coalesce(max(idPath), 0) - FROM path - """ -create_file = """ SELECT coalesce(max(idFile), 0) - FROM files - """ -create_person = """ SELECT coalesce(max(actor_id), 0) - FROM actor - """ -create_genre = """ SELECT coalesce(max(genre_id), 0) - FROM genre - """ -create_studio = """ SELECT coalesce(max(studio_id), 0) - FROM studio - """ -create_bookmark = """ SELECT coalesce(max(idBookmark), 0) - FROM bookmark - """ -create_tag = """ SELECT coalesce(max(tag_id), 0) - FROM tag - """ -create_unique_id = """ SELECT coalesce(max(uniqueid_id), 0) - FROM uniqueid - """ -create_rating = """ SELECT coalesce(max(rating_id), 0) - FROM rating - """ -create_movie = """ SELECT coalesce(max(idMovie), 0) - FROM movie - """ -create_set = """ SELECT coalesce(max(idSet), 0) - FROM sets - """ -create_country = """ SELECT coalesce(max(country_id), 0) - FROM country - """ -create_musicvideo = """ SELECT coalesce(max(idMVideo), 0) - FROM musicvideo - """ -create_tvshow = """ SELECT coalesce(max(idShow), 0) - FROM tvshow - """ -create_season = """ SELECT coalesce(max(idSeason), 0) - FROM seasons - """ -create_episode = """ SELECT coalesce(max(idEpisode), 0) - FROM episode - """ - - -get_path = """ SELECT idPath - FROM path - WHERE strPath = ? - """ -get_path_obj = [ "{Path}" - ] -get_file = """ SELECT idFile - FROM files - WHERE idPath = ? - AND strFilename = ? - """ -get_file_obj = [ "{FileId}" - ] -get_filename = """ SELECT strFilename - FROM files - WHERE idFile = ? - """ -get_person = """ SELECT actor_id - FROM actor - WHERE name = ? - COLLATE NOCASE - """ -get_genre = """ SELECT genre_id - FROM genre - WHERE name = ? - COLLATE NOCASE - """ -get_studio = """ SELECT studio_id - FROM studio - WHERE name = ? - COLLATE NOCASE - """ -get_tag = """ SELECT tag_id - FROM tag - WHERE name = ? - COLLATE NOCASE - """ -get_tag_movie_obj = [ "Favorite movies","{MovieId}","movie" - ] -get_tag_mvideo_obj = [ "Favorite musicvideos","{MvideoId}","musicvideo" - ] -get_tag_episode_obj = [ "Favorite tvshows","{KodiId}","tvshow" - ] -get_art = """ SELECT url - FROM art - WHERE media_id = ? - AND media_type = ? - AND type = ? - """ -get_movie = """ SELECT * - FROM movie - WHERE idMovie = ? - """ -get_movie_obj = [ "{MovieId}" - ] -get_rating = """ SELECT rating_id - FROM rating - WHERE media_type = ? - AND media_id = ? - """ -get_rating_movie_obj = [ "movie","{MovieId}" - ] -get_rating_episode_obj = [ "episode","{EpisodeId}" - ] -get_unique_id = """ SELECT uniqueid_id - FROM uniqueid - WHERE media_type = ? - AND media_id = ? - """ -get_unique_id_movie_obj = [ "movie","{MovieId}" - ] -get_unique_id_tvshow_obj = [ "tvshow","{ShowId}" - ] -get_unique_id_episode_obj = [ "episode","{EpisodeId}" - ] -get_country = """ SELECT country_id - FROM country - WHERE name = ? - COLLATE NOCASE - """ -get_set = """ SELECT idSet - FROM sets - WHERE strSet = ? - COLLATE NOCASE - """ -get_musicvideo = """ SELECT * - FROM musicvideo - WHERE idMVideo = ? - """ -get_musicvideo_obj = [ "{MvideoId}" - ] -get_tvshow = """ SELECT * - FROM tvshow - WHERE idShow = ? - """ -get_tvshow_obj = [ "{ShowId}" - ] -get_episode = """ SELECT * - FROM episode - WHERE idEpisode = ? - """ -get_episode_obj = [ "{EpisodeId}" - ] -get_season = """ SELECT idSeason - FROM seasons - WHERE idShow = ? - AND season = ? - """ -get_season_obj = [ "{Title}","{ShowId}","{Index}" - ] -get_season_special_obj = [ None,"{ShowId}",-1 - ] -get_season_episode_obj = [ None,"{ShowId}","{Season}" - ] -get_backdrops = """ SELECT url - FROM art - WHERE media_id = ? - AND media_type = ? - AND type LIKE ? - """ -get_art = """ SELECT url - FROM art - WHERE media_id = ? - AND media_type = ? - AND type = ? - """ -get_art_url = """ SELECT url, type - FROM art - WHERE media_id = ? - AND media_type = ? - """ -get_show_by_unique_id = """ SELECT idShow - FROM tvshow_view - WHERE uniqueid_value = ? +create_path = """ SELECT coalesce(max(idPath), 0) + FROM path + """ +create_file = """ SELECT coalesce(max(idFile), 0) + FROM files + """ +create_person = """ SELECT coalesce(max(actor_id), 0) + FROM actor + """ +create_genre = """ SELECT coalesce(max(genre_id), 0) + FROM genre + """ +create_studio = """ SELECT coalesce(max(studio_id), 0) + FROM studio + """ +create_bookmark = """ SELECT coalesce(max(idBookmark), 0) + FROM bookmark + """ +create_tag = """ SELECT coalesce(max(tag_id), 0) + FROM tag + """ +create_unique_id = """ SELECT coalesce(max(uniqueid_id), 0) + FROM uniqueid + """ +create_rating = """ SELECT coalesce(max(rating_id), 0) + FROM rating + """ +create_movie = """ SELECT coalesce(max(idMovie), 0) + FROM movie + """ +create_set = """ SELECT coalesce(max(idSet), 0) + FROM sets + """ +create_country = """ SELECT coalesce(max(country_id), 0) + FROM country + """ +create_musicvideo = """ SELECT coalesce(max(idMVideo), 0) + FROM musicvideo + """ +create_tvshow = """ SELECT coalesce(max(idShow), 0) + FROM tvshow + """ +create_season = """ SELECT coalesce(max(idSeason), 0) + FROM seasons + """ +create_episode = """ SELECT coalesce(max(idEpisode), 0) + FROM episode """ -get_total_episodes = """ SELECT totalCount - FROM tvshowcounts + +get_path = """ SELECT idPath + FROM path + WHERE strPath = ? + """ +get_path_obj = ["{Path}"] +get_file = """ SELECT idFile + FROM files + WHERE idPath = ? + AND strFilename = ? + """ +get_file_obj = ["{FileId}"] +get_filename = """ SELECT strFilename + FROM files + WHERE idFile = ? + """ +get_person = """ SELECT actor_id + FROM actor + WHERE name = ? + COLLATE NOCASE + """ +get_genre = """ SELECT genre_id + FROM genre + WHERE name = ? + COLLATE NOCASE + """ +get_studio = """ SELECT studio_id + FROM studio + WHERE name = ? + COLLATE NOCASE + """ +get_tag = """ SELECT tag_id + FROM tag + WHERE name = ? + COLLATE NOCASE + """ +get_tag_movie_obj = ["Favorite movies", "{MovieId}", "movie"] +get_tag_mvideo_obj = ["Favorite musicvideos", "{MvideoId}", "musicvideo"] +get_tag_episode_obj = ["Favorite tvshows", "{KodiId}", "tvshow"] +get_art = """ SELECT url + FROM art + WHERE media_id = ? + AND media_type = ? + AND type = ? + """ +get_movie = """ SELECT * + FROM movie + WHERE idMovie = ? + """ +get_movie_obj = ["{MovieId}"] +get_rating = """ SELECT rating_id + FROM rating + WHERE media_type = ? + AND media_id = ? + """ +get_rating_movie_obj = ["movie", "{MovieId}"] +get_rating_episode_obj = ["episode", "{EpisodeId}"] +get_unique_id = """ SELECT uniqueid_id + FROM uniqueid + WHERE media_type = ? + AND media_id = ? + """ +get_unique_id_movie_obj = ["movie", "{MovieId}"] +get_unique_id_tvshow_obj = ["tvshow", "{ShowId}"] +get_unique_id_episode_obj = ["episode", "{EpisodeId}"] +get_country = """ SELECT country_id + FROM country + WHERE name = ? + COLLATE NOCASE + """ +get_set = """ SELECT idSet + FROM sets + WHERE strSet = ? + COLLATE NOCASE + """ +get_musicvideo = """ SELECT * + FROM musicvideo + WHERE idMVideo = ? + """ +get_musicvideo_obj = ["{MvideoId}"] +get_tvshow = """ SELECT * + FROM tvshow + WHERE idShow = ? + """ +get_tvshow_obj = ["{ShowId}"] +get_episode = """ SELECT * + FROM episode + WHERE idEpisode = ? + """ +get_episode_obj = ["{EpisodeId}"] +get_season = """ SELECT idSeason + FROM seasons + WHERE idShow = ? + AND season = ? + """ +get_season_obj = ["{Title}", "{ShowId}", "{Index}"] +get_season_special_obj = [None, "{ShowId}", -1] +get_season_episode_obj = [None, "{ShowId}", "{Season}"] +get_backdrops = """ SELECT url + FROM art + WHERE media_id = ? + AND media_type = ? + AND type LIKE ? + """ +get_art = """ SELECT url + FROM art + WHERE media_id = ? + AND media_type = ? + AND type = ? + """ +get_art_url = """ SELECT url, type + FROM art + WHERE media_id = ? + AND media_type = ? + """ +get_show_by_unique_id = """ SELECT idShow + FROM tvshow_view + WHERE uniqueid_value = ? + """ + +get_total_episodes = """ SELECT totalCount + FROM tvshowcounts WHERE idShow = ? """ -get_total_episodes_obj = [ "{ParentId}" - ] +get_total_episodes_obj = ["{ParentId}"] - -add_path = """ INSERT INTO path(idPath, strPath) - VALUES (?, ?) - """ -add_path_obj = [ "{Path}" - ] -add_file = """ INSERT INTO files(idFile, idPath, strFilename) - VALUES (?, ?, ?) - """ -add_file_obj = [ "{PathId}","{Filename}" - ] -add_person = """ INSERT INTO actor(actor_id, name) - VALUES (?, ?) - """ -add_people_movie_obj = [ "{People}","{MovieId}","movie" - ] -add_people_mvideo_obj = [ "{People}","{MvideoId}","musicvideo" - ] -add_people_tvshow_obj = [ "{People}","{ShowId}","tvshow" - ] -add_people_episode_obj = [ "{People}","{EpisodeId}","episode" - ] -add_actor_link = """ INSERT INTO actor_link(actor_id, media_id, media_type, role, cast_order) - VALUES (?, ?, ?, ?, ?) - """ -add_link = """ INSERT INTO {LinkType}(actor_id, media_id, media_type) - VALUES (?, ?, ?) - """ -add_genre = """ INSERT INTO genre(genre_id, name) - VALUES (?, ?) - """ -add_genres_movie_obj = [ "{Genres}","{MovieId}","movie" - ] -add_genres_mvideo_obj = [ "{Genres}","{MvideoId}","musicvideo" - ] -add_genres_tvshow_obj = [ "{Genres}","{ShowId}","tvshow" - ] -add_studio = """ INSERT INTO studio(studio_id, name) - VALUES (?, ?) - """ -add_studios_movie_obj = [ "{Studios}","{MovieId}","movie" - ] -add_studios_mvideo_obj = [ "{Studios}","{MvideoId}","musicvideo" - ] -add_studios_tvshow_obj = [ "{Studios}","{ShowId}","tvshow" - ] -add_bookmark = """ INSERT INTO bookmark(idBookmark, idFile, timeInSeconds, totalTimeInSeconds, player, type) - VALUES (?, ?, ?, ?, ?, ?) - """ -add_bookmark_obj = [ "{FileId}","{PlayCount}","{DatePlayed}","{Resume}","{Runtime}","DVDPlayer",1 - ] -add_streams_obj = [ "{FileId}","{Streams}","{Runtime}" - ] -add_stream_video = """ INSERT INTO streamdetails(idFile, iStreamType, strVideoCodec, fVideoAspect, iVideoWidth, - iVideoHeight, iVideoDuration, strStereoMode) - VALUES (?, ?, ?, ?, ?, ?, ?, ?) - """ -add_stream_video_obj = [ "{FileId}",0,"{codec}","{aspect}","{width}","{height}","{Runtime}","{3d}" - ] -add_stream_audio = """ INSERT INTO streamdetails(idFile, iStreamType, strAudioCodec, iAudioChannels, strAudioLanguage) - VALUES (?, ?, ?, ?, ?) - """ -add_stream_audio_obj = [ "{FileId}",1,"{codec}","{channels}","{language}" - ] -add_stream_sub = """ INSERT INTO streamdetails(idFile, iStreamType, strSubtitleLanguage) - VALUES (?, ?, ?) - """ -add_stream_sub_obj = [ "{FileId}",2,"{language}" - ] -add_tag = """ INSERT INTO tag(tag_id, name) - VALUES (?, ?) - """ -add_tags_movie_obj = [ "{Tags}","{MovieId}","movie" - ] -add_tags_mvideo_obj = [ "{Tags}","{MvideoId}","musicvideo" - ] -add_tags_tvshow_obj = [ "{Tags}","{ShowId}","tvshow" - ] -add_art = """ INSERT INTO art(media_id, media_type, type, url) - VALUES (?, ?, ?, ?) - """ -add_movie = """ INSERT INTO movie(idMovie, idFile, c00, c01, c02, c03, c04, c05, c06, c07, - c09, c10, c11, c12, c14, c15, c16, c18, c19, c21, userrating, premiered) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_movie_obj = [ "{MovieId}","{FileId}","{Title}","{Plot}","{ShortPlot}","{Tagline}", - "{Votes}","{RatingId}","{Writers}","{Year}","{Unique}","{SortTitle}", - "{Runtime}","{Mpaa}","{Genre}","{Directors}","{Title}","{Studio}", - "{Trailer}","{Country}","{CriticRating}","{Year}" - ] -add_rating = """ INSERT INTO rating(rating_id, media_id, media_type, rating_type, rating, votes) - VALUES (?, ?, ?, ?, ?, ?) - """ -add_rating_movie_obj = [ "{RatingId}","{MovieId}","movie","default","{Rating}","{Votes}" - ] -add_rating_tvshow_obj = [ "{RatingId}","{ShowId}","tvshow","default","{Rating}","{Votes}" - ] -add_rating_episode_obj = [ "{RatingId}","{EpisodeId}","episode","default","{Rating}","{Votes}" - ] -add_unique_id = """ INSERT INTO uniqueid(uniqueid_id, media_id, media_type, value, type) - VALUES (?, ?, ?, ?, ?) - """ -add_unique_id_movie_obj = [ "{Unique}","{MovieId}","movie","{UniqueId}","{ProviderName}" - ] -add_unique_id_tvshow_obj = [ "{Unique}","{ShowId}","tvshow","{UniqueId}","{ProviderName}" - ] -add_unique_id_episode_obj = [ "{Unique}","{EpisodeId}","episode","{UniqueId}","{ProviderName}" - ] -add_country = """ INSERT INTO country(country_id, name) - VALUES (?, ?) - """ -add_set = """ INSERT INTO sets(idSet, strSet, strOverview) - VALUES (?, ?, ?) - """ -add_set_obj = [ "{Title}","{Overview}" - ] -add_musicvideo = """ INSERT INTO musicvideo(idMVideo,idFile, c00, c04, c05, c06, c07, c08, c09, c10, - c11, c12, premiered) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_musicvideo_obj = [ "{MvideoId}","{FileId}","{Title}","{Runtime}","{Directors}","{Studio}","{Year}", - "{Plot}","{Album}","{Artists}","{Genre}","{Index}","{Premiere}" - ] -add_tvshow = """ INSERT INTO tvshow(idShow, c00, c01, c02, c04, c05, c08, c09, c10, c12, c13, c14, c15) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_tvshow_obj = [ "{ShowId}","{Title}","{Plot}","{Status}","{RatingId}","{Premiere}","{Genre}","{Title}", - "disintegrate browse bug", "{Unique}","{Mpaa}","{Studio}","{SortTitle}" - ] -add_season = """ INSERT INTO seasons(idSeason, idShow, season) - VALUES (?, ?, ?) - """ -add_episode = """ INSERT INTO episode(idEpisode, idFile, c00, c01, c03, c04, c05, c09, c10, c12, c13, c14, - idShow, c15, c16, idSeason) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_episode_obj = [ "{EpisodeId}","{FileId}","{Title}","{Plot}","{RatingId}","{Writers}","{Premiere}","{Runtime}", - "{Directors}","{Season}","{Index}","{Title}","{ShowId}","{AirsBeforeSeason}", - "{AirsBeforeEpisode}","{SeasonId}" - ] -add_art = """ INSERT INTO art(media_id, media_type, type, url) - VALUES (?, ?, ?, ?) - """ +add_path = """ INSERT INTO path(idPath, strPath) + VALUES (?, ?) + """ +add_path_obj = ["{Path}"] +add_file = """ INSERT INTO files(idFile, idPath, strFilename) + VALUES (?, ?, ?) + """ +add_file_obj = ["{PathId}", "{Filename}"] +add_person = """ INSERT INTO actor(actor_id, name) + VALUES (?, ?) + """ +add_people_movie_obj = ["{People}", "{MovieId}", "movie"] +add_people_mvideo_obj = ["{People}", "{MvideoId}", "musicvideo"] +add_people_tvshow_obj = ["{People}", "{ShowId}", "tvshow"] +add_people_episode_obj = ["{People}", "{EpisodeId}", "episode"] +add_actor_link = """ INSERT INTO actor_link(actor_id, media_id, media_type, role, cast_order) + VALUES (?, ?, ?, ?, ?) + """ +add_link = """ INSERT INTO {LinkType}(actor_id, media_id, media_type) + VALUES (?, ?, ?) + """ +add_genre = """ INSERT INTO genre(genre_id, name) + VALUES (?, ?) + """ +add_genres_movie_obj = ["{Genres}", "{MovieId}", "movie"] +add_genres_mvideo_obj = ["{Genres}", "{MvideoId}", "musicvideo"] +add_genres_tvshow_obj = ["{Genres}", "{ShowId}", "tvshow"] +add_studio = """ INSERT INTO studio(studio_id, name) + VALUES (?, ?) + """ +add_studios_movie_obj = ["{Studios}", "{MovieId}", "movie"] +add_studios_mvideo_obj = ["{Studios}", "{MvideoId}", "musicvideo"] +add_studios_tvshow_obj = ["{Studios}", "{ShowId}", "tvshow"] +add_bookmark = """ INSERT INTO bookmark(idBookmark, idFile, timeInSeconds, totalTimeInSeconds, player, type) + VALUES (?, ?, ?, ?, ?, ?) + """ +add_bookmark_obj = ["{FileId}", "{PlayCount}", "{DatePlayed}", "{Resume}", "{Runtime}", "DVDPlayer", 1] +add_streams_obj = ["{FileId}", "{Streams}", "{Runtime}"] +add_stream_video = """ INSERT INTO streamdetails(idFile, iStreamType, strVideoCodec, fVideoAspect, iVideoWidth, + iVideoHeight, iVideoDuration, strStereoMode) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + """ +add_stream_video_obj = ["{FileId}", 0, "{codec}", "{aspect}", "{width}", "{height}", "{Runtime}", "{3d}"] +add_stream_audio = """ INSERT INTO streamdetails(idFile, iStreamType, strAudioCodec, iAudioChannels, strAudioLanguage) + VALUES (?, ?, ?, ?, ?) + """ +add_stream_audio_obj = ["{FileId}", 1, "{codec}", "{channels}", "{language}"] +add_stream_sub = """ INSERT INTO streamdetails(idFile, iStreamType, strSubtitleLanguage) + VALUES (?, ?, ?) + """ +add_stream_sub_obj = ["{FileId}", 2, "{language}"] +add_tag = """ INSERT INTO tag(tag_id, name) + VALUES (?, ?) + """ +add_tags_movie_obj = ["{Tags}", "{MovieId}", "movie"] +add_tags_mvideo_obj = ["{Tags}", "{MvideoId}", "musicvideo"] +add_tags_tvshow_obj = ["{Tags}", "{ShowId}", "tvshow"] +add_art = """ INSERT INTO art(media_id, media_type, type, url) + VALUES (?, ?, ?, ?) + """ +add_movie = """ INSERT INTO movie(idMovie, idFile, c00, c01, c02, c03, c04, c05, c06, c07, + c09, c10, c11, c12, c14, c15, c16, c18, c19, c21, userrating, premiered) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_movie_obj = ["{MovieId}", "{FileId}", "{Title}", "{Plot}", "{ShortPlot}", "{Tagline}", + "{Votes}", "{RatingId}", "{Writers}", "{Year}", "{Unique}", "{SortTitle}", + "{Runtime}", "{Mpaa}", "{Genre}", "{Directors}", "{Title}", "{Studio}", + "{Trailer}", "{Country}", "{CriticRating}", "{Year}"] +add_rating = """ INSERT INTO rating(rating_id, media_id, media_type, rating_type, rating, votes) + VALUES (?, ?, ?, ?, ?, ?) + """ +add_rating_movie_obj = ["{RatingId}", "{MovieId}", "movie", "default", "{Rating}", "{Votes}"] +add_rating_tvshow_obj = ["{RatingId}", "{ShowId}", "tvshow", "default", "{Rating}", "{Votes}"] +add_rating_episode_obj = ["{RatingId}", "{EpisodeId}", "episode", "default", "{Rating}", "{Votes}"] +add_unique_id = """ INSERT INTO uniqueid(uniqueid_id, media_id, media_type, value, type) + VALUES (?, ?, ?, ?, ?) + """ +add_unique_id_movie_obj = ["{Unique}", "{MovieId}", "movie", "{UniqueId}", "{ProviderName}"] +add_unique_id_tvshow_obj = ["{Unique}", "{ShowId}", "tvshow", "{UniqueId}", "{ProviderName}"] +add_unique_id_episode_obj = ["{Unique}", "{EpisodeId}", "episode", "{UniqueId}", "{ProviderName}"] +add_country = """ INSERT INTO country(country_id, name) + VALUES (?, ?) + """ +add_set = """ INSERT INTO sets(idSet, strSet, strOverview) + VALUES (?, ?, ?) + """ +add_set_obj = ["{Title}", "{Overview}"] +add_musicvideo = """ INSERT INTO musicvideo(idMVideo, idFile, c00, c04, c05, c06, c07, c08, c09, c10, + c11, c12, premiered) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_musicvideo_obj = ["{MvideoId}", "{FileId}", "{Title}", "{Runtime}", "{Directors}", "{Studio}", "{Year}", + "{Plot}", "{Album}", "{Artists}", "{Genre}", "{Index}", "{Premiere}"] +add_tvshow = """ INSERT INTO tvshow(idShow, c00, c01, c02, c04, c05, c08, c09, c10, c12, c13, c14, c15) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_tvshow_obj = ["{ShowId}", "{Title}", "{Plot}", "{Status}", "{RatingId}", "{Premiere}", "{Genre}", "{Title}", + "disintegrate browse bug", "{Unique}", "{Mpaa}", "{Studio}", "{SortTitle}"] +add_season = """ INSERT INTO seasons(idSeason, idShow, season) + VALUES (?, ?, ?) + """ +add_episode = """ INSERT INTO episode(idEpisode, idFile, c00, c01, c03, c04, c05, c09, c10, c12, c13, c14, + idShow, c15, c16, idSeason) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_episode_obj = ["{EpisodeId}", "{FileId}", "{Title}", "{Plot}", "{RatingId}", "{Writers}", "{Premiere}", "{Runtime}", + "{Directors}", "{Season}", "{Index}", "{Title}", "{ShowId}", "{AirsBeforeSeason}", + "{AirsBeforeEpisode}", "{SeasonId}"] +add_art = """ INSERT INTO art(media_id, media_type, type, url) + VALUES (?, ?, ?, ?) + """ +update_path = """ UPDATE path + SET strPath = ?, strContent = ?, strScraper = ?, noUpdate = ? + WHERE idPath = ? + """ +update_path_movie_obj = ["{Path}", "movies", "metadata.local", 1, "{PathId}"] +update_path_toptvshow_obj = ["{TopLevel}", "tvshows", "metadata.local", 1, "{TopPathId}"] +update_path_tvshow_obj = ["{Path}", None, None, 1, "{PathId}"] +update_path_episode_obj = ["{Path}", None, None, 1, "{PathId}"] +update_path_mvideo_obj = ["{Path}", "musicvideos", None, 1, "{PathId}"] +update_file = """ UPDATE files + SET idPath = ?, strFilename = ?, dateAdded = ? + WHERE idFile = ? + """ +update_file_obj = ["{PathId}", "{Filename}", "{DateAdded}", "{FileId}"] +update_genres = """ INSERT OR REPLACE INTO genre_link(genre_id, media_id, media_type) + VALUES (?, ?, ?) + """ +update_studios = """ INSERT OR REPLACE INTO studio_link(studio_id, media_id, media_type) + VALUES (?, ?, ?) + """ +update_playcount = """ UPDATE files + SET playCount = ?, lastPlayed = ? + WHERE idFile = ? + """ +update_tag = """ INSERT OR REPLACE INTO tag_link(tag_id, media_id, media_type) + VALUES (?, ?, ?) + """ +update_art = """ UPDATE art + SET url = ? + WHERE media_id = ? + AND media_type = ? + AND type = ? + """ +update_actor = """ INSERT OR REPLACE INTO actor_link(actor_id, media_id, media_type, role, cast_order) + VALUES (?, ?, ?, ?, ?) + """ -update_path = """ UPDATE path - SET strPath = ?, strContent = ?, strScraper = ?, noUpdate = ? - WHERE idPath = ? - """ -update_path_movie_obj = [ "{Path}","movies","metadata.local",1,"{PathId}" - ] -update_path_toptvshow_obj = [ "{TopLevel}","tvshows","metadata.local",1,"{TopPathId}" - ] -update_path_tvshow_obj = [ "{Path}",None,None,1,"{PathId}" - ] -update_path_episode_obj = [ "{Path}",None,None,1,"{PathId}" - ] -update_path_mvideo_obj = [ "{Path}","musicvideos",None,1,"{PathId}" - ] -update_file = """ UPDATE files - SET idPath = ?, strFilename = ?, dateAdded = ? - WHERE idFile = ? - """ -update_file_obj = [ "{PathId}","{Filename}","{DateAdded}","{FileId}" - ] -update_genres = """ INSERT OR REPLACE INTO genre_link(genre_id, media_id, media_type) - VALUES (?, ?, ?) - """ -update_studios = """ INSERT OR REPLACE INTO studio_link(studio_id, media_id, media_type) - VALUES (?, ?, ?) - """ -update_playcount = """ UPDATE files - SET playCount = ?, lastPlayed = ? - WHERE idFile = ? - """ -update_tag = """ INSERT OR REPLACE INTO tag_link(tag_id, media_id, media_type) - VALUES (?, ?, ?) - """ -update_art = """ UPDATE art - SET url = ? - WHERE media_id = ? - AND media_type = ? - AND type = ? - """ -update_actor = """ INSERT OR REPLACE INTO actor_link(actor_id, media_id, media_type, role, cast_order) - VALUES (?, ?, ?, ?, ?) - """ - -update_link = """ INSERT OR REPLACE INTO {LinkType}(actor_id, media_id, media_type) - VALUES (?, ?, ?) - """ -update_movie = """ UPDATE movie - SET c00 = ?, c01 = ?, c02 = ?, c03 = ?, c04 = ?, c05 = ?, c06 = ?, - c07 = ?, c09 = ?, c10 = ?, c11 = ?, c12 = ?, c14 = ?, c15 = ?, - c16 = ?, c18 = ?, c19 = ?, c21 = ?, userrating = ?, premiered = ? - WHERE idMovie = ? - """ -update_movie_obj = [ "{Title}","{Plot}","{ShortPlot}","{Tagline}","{Votes}","{RatingId}", - "{Writers}","{Year}","{Unique}","{SortTitle}","{Runtime}", - "{Mpaa}","{Genre}","{Directors}","{Title}","{Studio}","{Trailer}", - "{Country}","{CriticRating}","{Year}","{MovieId}" - ] -update_rating = """ UPDATE rating - SET media_id = ?, media_type = ?, rating_type = ?, rating = ?, votes = ? - WHERE rating_id = ? - """ -update_rating_movie_obj = [ "{MovieId}","movie","default","{Rating}","{Votes}","{RatingId}" - ] -update_rating_tvshow_obj = [ "{ShowId}","tvshow","default","{Rating}","{Votes}","{RatingId}" - ] -update_rating_episode_obj = [ "{EpisodeId}","episode","default","{Rating}","{Votes}","{RatingId}" - ] -update_unique_id = """ UPDATE uniqueid - SET media_id = ?, media_type = ?, value = ?, type = ? - WHERE uniqueid_id = ? - """ -update_unique_id_movie_obj = [ "{MovieId}","movie","{UniqueId}","{ProviderName}","{Unique}" - ] -update_unique_id_tvshow_obj = [ "{ShowId}","tvshow","{UniqueId}","{ProviderName}","{Unique}" - ] -update_unique_id_episode_obj = [ "{EpisodeId}","episode","{UniqueId}","{ProviderName}","{Unique}" - ] -update_country = """ INSERT OR REPLACE INTO country_link(country_id, media_id, media_type) - VALUES (?, ?, ?) - """ -update_country_obj = [ "{Countries}","{MovieId}","movie" - ] -update_set = """ UPDATE sets - SET strSet = ?, strOverview = ? - WHERE idSet = ? - """ -update_set_obj = [ "{Title}", "{Overview}", "{SetId}" - ] -update_movie_set = """ UPDATE movie - SET idSet = ? - WHERE idMovie = ? - """ -update_movie_set_obj = [ "{SetId}","{MovieId}" - ] -update_musicvideo = """ UPDATE musicvideo - SET c00 = ?, c04 = ?, c05 = ?, c06 = ?, c07 = ?, c08 = ?, c09 = ?, c10 = ?, - c11 = ?, c12 = ?, premiered = ? - WHERE idMVideo = ? - """ -update_musicvideo_obj = [ "{Title}","{Runtime}","{Directors}","{Studio}","{Year}","{Plot}","{Album}", - "{Artists}","{Genre}","{Index}","{Premiere}","{MvideoId}" - ] -update_tvshow = """ UPDATE tvshow - SET c00 = ?, c01 = ?, c02 = ?, c04 = ?, c05 = ?, c08 = ?, c09 = ?, c10 = ?, - c12 = ?, c13 = ?, c14 = ?, c15 = ? - WHERE idShow = ? - """ -update_tvshow_obj = [ "{Title}","{Plot}","{Status}","{RatingId}","{Premiere}","{Genre}","{Title}", - "disintegrate browse bug","{Unique}","{Mpaa}","{Studio}","{SortTitle}","{ShowId}" - ] -update_tvshow_link = """ INSERT OR REPLACE INTO tvshowlinkpath(idShow, idPath) - VALUES (?, ?) - """ -update_tvshow_link_obj = [ "{ShowId}","{PathId}" - ] -update_season = """ UPDATE seasons - SET name = ? - WHERE idSeason = ? - """ -update_episode = """ UPDATE episode - SET c00 = ?, c01 = ?, c03 = ?, c04 = ?, c05 = ?, c09 = ?, c10 = ?, - c12 = ?, c13 = ?, c14 = ?, c15 = ?, c16 = ?, idSeason = ?, idShow = ? - WHERE idEpisode = ? - """ -update_episode_obj = [ "{Title}","{Plot}","{RatingId}","{Writers}","{Premiere}","{Runtime}","{Directors}", - "{Season}","{Index}","{Title}","{AirsBeforeSeason}","{AirsBeforeEpisode}","{SeasonId}", - "{ShowId}","{EpisodeId}" - ] +update_link = """ INSERT OR REPLACE INTO {LinkType}(actor_id, media_id, media_type) + VALUES (?, ?, ?) + """ +update_movie = """ UPDATE movie + SET c00 = ?, c01 = ?, c02 = ?, c03 = ?, c04 = ?, c05 = ?, c06 = ?, + c07 = ?, c09 = ?, c10 = ?, c11 = ?, c12 = ?, c14 = ?, c15 = ?, + c16 = ?, c18 = ?, c19 = ?, c21 = ?, userrating = ?, premiered = ? + WHERE idMovie = ? + """ +update_movie_obj = ["{Title}", "{Plot}", "{ShortPlot}", "{Tagline}", "{Votes}", "{RatingId}", + "{Writers}", "{Year}", "{Unique}", "{SortTitle}", "{Runtime}", + "{Mpaa}", "{Genre}", "{Directors}", "{Title}", "{Studio}", "{Trailer}", + "{Country}", "{CriticRating}", "{Year}", "{MovieId}"] +update_rating = """ UPDATE rating + SET media_id = ?, media_type = ?, rating_type = ?, rating = ?, votes = ? + WHERE rating_id = ? + """ +update_rating_movie_obj = ["{MovieId}", "movie", "default", "{Rating}", "{Votes}", "{RatingId}"] +update_rating_tvshow_obj = ["{ShowId}", "tvshow", "default", "{Rating}", "{Votes}", "{RatingId}"] +update_rating_episode_obj = ["{EpisodeId}", "episode", "default", "{Rating}", "{Votes}", "{RatingId}"] +update_unique_id = """ UPDATE uniqueid + SET media_id = ?, media_type = ?, value = ?, type = ? + WHERE uniqueid_id = ? + """ +update_unique_id_movie_obj = ["{MovieId}", "movie", "{UniqueId}", "{ProviderName}", "{Unique}"] +update_unique_id_tvshow_obj = ["{ShowId}", "tvshow", "{UniqueId}", "{ProviderName}", "{Unique}"] +update_unique_id_episode_obj = ["{EpisodeId}", "episode", "{UniqueId}", "{ProviderName}", "{Unique}"] +update_country = """ INSERT OR REPLACE INTO country_link(country_id, media_id, media_type) + VALUES (?, ?, ?) + """ +update_country_obj = ["{Countries}", "{MovieId}", "movie"] +update_set = """ UPDATE sets + SET strSet = ?, strOverview = ? + WHERE idSet = ? + """ +update_set_obj = ["{Title}", "{Overview}", "{SetId}"] +update_movie_set = """ UPDATE movie + SET idSet = ? + WHERE idMovie = ? + """ +update_movie_set_obj = ["{SetId}", "{MovieId}"] +update_musicvideo = """ UPDATE musicvideo + SET c00 = ?, c04 = ?, c05 = ?, c06 = ?, c07 = ?, c08 = ?, c09 = ?, c10 = ?, + c11 = ?, c12 = ?, premiered = ? + WHERE idMVideo = ? + """ +update_musicvideo_obj = ["{Title}", "{Runtime}", "{Directors}", "{Studio}", "{Year}", "{Plot}", "{Album}", + "{Artists}", "{Genre}", "{Index}", "{Premiere}", "{MvideoId}"] +update_tvshow = """ UPDATE tvshow + SET c00 = ?, c01 = ?, c02 = ?, c04 = ?, c05 = ?, c08 = ?, c09 = ?, c10 = ?, + c12 = ?, c13 = ?, c14 = ?, c15 = ? + WHERE idShow = ? + """ +update_tvshow_obj = ["{Title}", "{Plot}", "{Status}", "{RatingId}", "{Premiere}", "{Genre}", "{Title}", + "disintegrate browse bug", "{Unique}", "{Mpaa}", "{Studio}", "{SortTitle}", "{ShowId}"] +update_tvshow_link = """ INSERT OR REPLACE INTO tvshowlinkpath(idShow, idPath) + VALUES (?, ?) + """ +update_tvshow_link_obj = ["{ShowId}", "{PathId}"] +update_season = """ UPDATE seasons + SET name = ? + WHERE idSeason = ? + """ +update_episode = """ UPDATE episode + SET c00 = ?, c01 = ?, c03 = ?, c04 = ?, c05 = ?, c09 = ?, c10 = ?, + c12 = ?, c13 = ?, c14 = ?, c15 = ?, c16 = ?, idSeason = ?, idShow = ? + WHERE idEpisode = ? + """ +update_episode_obj = ["{Title}", "{Plot}", "{RatingId}", "{Writers}", "{Premiere}", "{Runtime}", "{Directors}", + "{Season}", "{Index}", "{Title}", "{AirsBeforeSeason}", "{AirsBeforeEpisode}", "{SeasonId}", + "{ShowId}", "{EpisodeId}"] - -delete_path = """ DELETE FROM path - WHERE idPath = ? - """ -delete_path_obj = [ "{PathId}" - ] -delete_file = """ DELETE FROM files - WHERE idFile = ? - """ -delete_file_obj = [ "{Path}","{Filename}" - ] -delete_file_by_path = """ DELETE FROM files - WHERE idPath = ? - AND strFileName = ? - """ -delete_genres = """ DELETE FROM genre_link - WHERE media_id = ? - AND media_type = ? - """ -delete_bookmark = """ DELETE FROM bookmark - WHERE idFile = ? - """ -delete_streams = """ DELETE FROM streamdetails - WHERE idFile = ? - """ -delete_tags = """ DELETE FROM tag_link - WHERE media_id = ? - AND media_type = ? - """ -delete_tag = """ DELETE FROM tag_link - WHERE tag_id = ? - AND media_id = ? - AND media_type = ? - """ -delete_tag_movie_obj = [ "Favorite movies","{MovieId}","movie" - ] -delete_tag_mvideo_obj = [ "Favorite musicvideos","{MvideoId}","musicvideo" - ] -delete_tag_episode_obj = [ "Favorite tvshows","{KodiId}","tvshow" - ] -delete_movie = """ DELETE FROM movie - WHERE idMovie = ? - """ -delete_movie_obj = [ "{KodiId}","{FileId}" - ] -delete_set = """ DELETE FROM sets - WHERE idSet = ? - """ -delete_set_obj = [ "{KodiId}" - ] -delete_movie_set = """ UPDATE movie - SET idSet = null - WHERE idMovie = ? - """ -delete_movie_set_obj = [ "{MovieId}" - ] -delete_musicvideo = """ DELETE FROM musicvideo - WHERE idMVideo = ? - """ -delete_musicvideo_obj = [ "{MvideoId}", "{FileId}" - ] -delete_tvshow = """ DELETE FROM tvshow - WHERE idShow = ? - """ -delete_season = """ DELETE FROM seasons - WHERE idSeason = ? - """ -delete_episode = """ DELETE FROM episode - WHERE idEpisode = ? - """ -delete_backdrops = """ DELETE FROM art - WHERE media_id = ? - AND media_type = ? - AND type LIKE ? - """ +delete_path = """ DELETE FROM path + WHERE idPath = ? + """ +delete_path_obj = ["{PathId}"] +delete_file = """ DELETE FROM files + WHERE idFile = ? + """ +delete_file_obj = ["{Path}", "{Filename}"] +delete_file_by_path = """ DELETE FROM files + WHERE idPath = ? + AND strFileName = ? + """ +delete_genres = """ DELETE FROM genre_link + WHERE media_id = ? + AND media_type = ? + """ +delete_bookmark = """ DELETE FROM bookmark + WHERE idFile = ? + """ +delete_streams = """ DELETE FROM streamdetails + WHERE idFile = ? + """ +delete_tags = """ DELETE FROM tag_link + WHERE media_id = ? + AND media_type = ? + """ +delete_tag = """ DELETE FROM tag_link + WHERE tag_id = ? + AND media_id = ? + AND media_type = ? + """ +delete_tag_movie_obj = ["Favorite movies", "{MovieId}", "movie"] +delete_tag_mvideo_obj = ["Favorite musicvideos", "{MvideoId}", "musicvideo"] +delete_tag_episode_obj = ["Favorite tvshows", "{KodiId}", "tvshow"] +delete_movie = """ DELETE FROM movie + WHERE idMovie = ? + """ +delete_movie_obj = ["{KodiId}", "{FileId}"] +delete_set = """ DELETE FROM sets + WHERE idSet = ? + """ +delete_set_obj = ["{KodiId}"] +delete_movie_set = """ UPDATE movie + SET idSet = null + WHERE idMovie = ? + """ +delete_movie_set_obj = ["{MovieId}"] +delete_musicvideo = """ DELETE FROM musicvideo + WHERE idMVideo = ? + """ +delete_musicvideo_obj = ["{MvideoId}", "{FileId}"] +delete_tvshow = """ DELETE FROM tvshow + WHERE idShow = ? + """ +delete_season = """ DELETE FROM seasons + WHERE idSeason = ? + """ +delete_episode = """ DELETE FROM episode + WHERE idEpisode = ? + """ +delete_backdrops = """ DELETE FROM art + WHERE media_id = ? + AND media_type = ? + AND type LIKE ? + """ diff --git a/resources/lib/objects/kodi/queries_music.py b/resources/lib/objects/kodi/queries_music.py index 069d97ef..fd163bfc 100644 --- a/resources/lib/objects/kodi/queries_music.py +++ b/resources/lib/objects/kodi/queries_music.py @@ -1,238 +1,212 @@ -create_artist = """ SELECT coalesce(max(idArtist), 1) - FROM artist - """ -create_album = """ SELECT coalesce(max(idAlbum), 0) - FROM album - """ -create_song = """ SELECT coalesce(max(idSong), 0) - FROM song - """ -create_genre = """ SELECT coalesce(max(idGenre), 0) - FROM genre - """ - - - -get_artist = """ SELECT idArtist, strArtist - FROM artist - WHERE strMusicBrainzArtistID = ? - """ -get_artist_obj = [ "{ArtistId}","{Name}","{UniqueId}" - ] -get_artist_by_name = """ SELECT idArtist - FROM artist - WHERE strArtist = ? - COLLATE NOCASE - """ -get_artist_by_id = """ SELECT * - FROM artist - WHERE idArtist = ? - """ -get_artist_by_id_obj = [ "{ArtistId}" - ] -get_album_by_id = """ SELECT * - FROM album - WHERE idAlbum = ? - """ -get_album_by_id_obj = [ "{AlbumId}" - ] -get_song_by_id = """ SELECT * - FROM song - WHERE idSong = ? - """ -get_song_by_id_obj = [ "{SongId}" - ] -get_album = """ SELECT idAlbum - FROM album - WHERE strMusicBrainzAlbumID = ? - """ -get_album_obj = [ "{AlbumId}","{Title}","{UniqueId}","{Artists}","album" - ] -get_album_by_name = """ SELECT idAlbum, strArtists - FROM album - WHERE strAlbum = ? - """ -get_album_by_name72 = """ SELECT idAlbum, strArtistDisp - FROM album - WHERE strAlbum = ? - """ -get_album_artist = """ SELECT strArtists - FROM album - WHERE idAlbum = ? - """ -get_album_artist72 = """ SELECT strArtistDisp - FROM album - WHERE idAlbum = ? - """ -get_album_artist_obj = [ "{AlbumId}","{strAlbumArtists}" - ] -get_genre = """ SELECT idGenre - FROM genre - WHERE strGenre = ? - COLLATE NOCASE - """ -get_total_episodes = """ SELECT totalCount - FROM tvshowcounts - WHERE idShow = ? - """ - - - -add_artist = """ INSERT INTO artist(idArtist, strArtist, strMusicBrainzArtistID) - VALUES (?, ?, ?) - """ -add_album = """ INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType) - VALUES (?, ?, ?, ?) - """ -add_album72 = """ INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType, bScrapedMBID) - VALUES (?, ?, ?, ?, 1) - """ -add_single = """ INSERT INTO album(idAlbum, strGenres, iYear, strReleaseType) - VALUES (?, ?, ?, ?) - """ -add_single_obj = [ "{AlbumId}","{Genre}","{Year}","single" - ] -add_song = """ INSERT INTO song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, - iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed, - rating, comment, dateAdded) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_song72 = """ INSERT INTO song(idSong, idAlbum, idPath, strArtistDisp, strGenres, strTitle, iTrack, - iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed, - rating, comment, dateAdded) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """ -add_song_obj = [ "{SongId}","{AlbumId}","{PathId}","{Artists}","{Genre}","{Title}","{Index}", - "{Runtime}","{Year}","{Filename}","{UniqueId}","{PlayCount}","{DatePlayed}","{Rating}", - "{Comment}","{DateAdded}" - ] -add_genre = """ INSERT INTO genre(idGenre, strGenre) - VALUES (?, ?) - """ -add_genres_obj = [ "{AlbumId}","{Genres}","album" - ] - - - -update_path = """ UPDATE path - SET strPath = ? - WHERE idPath = ? - """ -update_path_obj = [ "{Path}","{PathId}" - ] -update_role = """ INSERT OR REPLACE INTO role(idRole, strRole) - VALUES (?, ?) - """ -update_role_obj = [ 1,"Composer" - ] -update_artist_name = """ UPDATE artist - SET strArtist = ? - WHERE idArtist = ? - """ -update_artist_name_obj = [ "{Name}","{ArtistId}" - ] -update_artist = """ UPDATE artist - SET strGenres = ?, strBiography = ?, strImage = ?, strFanart = ?, lastScraped = ? - WHERE idArtist = ? - """ -update_link = """ INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist) - VALUES (?, ?, ?) - """ -update_link_obj = [ "{ArtistId}","{AlbumId}","{Name}" - ] -update_discography = """ INSERT OR REPLACE INTO discography(idArtist, strAlbum, strYear) - VALUES (?, ?, ?) - """ -update_discography_obj = [ "{ArtistId}","{Title}","{Year}" - ] -update_album = """ UPDATE album - SET strArtists = ?, iYear = ?, strGenres = ?, strReview = ?, strImage = ?, - iUserrating = ?, lastScraped = ?, strReleaseType = ? - WHERE idAlbum = ? - """ -update_album72 = """ UPDATE album - SET strArtistDisp = ?, iYear = ?, strGenres = ?, strReview = ?, strImage = ?, - iUserrating = ?, lastScraped = ?, bScrapedMBID = 1, strReleaseType = ? - WHERE idAlbum = ? - """ -update_album_obj = [ "{Artists}","{Year}","{Genre}","{Bio}","{Thumb}","{Rating}","{LastScraped}", - "album","{AlbumId}" - - ] -update_album_artist = """ UPDATE album - SET strArtists = ? - WHERE idAlbum = ? - """ -update_album_artist72 = """ UPDATE album - SET strArtistDisp = ? - WHERE idAlbum = ? - """ -update_song = """ UPDATE song - SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?, - iDuration = ?, iYear = ?, strFilename = ?, iTimesPlayed = ?, lastplayed = ?, - rating = ?, comment = ?, dateAdded = ? - WHERE idSong = ? - """ -update_song72 = """ UPDATE song - SET idAlbum = ?, strArtistDisp = ?, strGenres = ?, strTitle = ?, iTrack = ?, - iDuration = ?, iYear = ?, strFilename = ?, iTimesPlayed = ?, lastplayed = ?, - rating = ?, comment = ?, dateAdded = ? - WHERE idSong = ? - """ -update_song_obj = [ "{AlbumId}","{Artists}","{Genre}","{Title}","{Index}","{Runtime}","{Year}", - "{Filename}","{PlayCount}","{DatePlayed}","{Rating}","{Comment}", - "{DateAdded}","{SongId}" - ] -update_song_artist = """ INSERT OR REPLACE INTO song_artist(idArtist, idSong, idRole, iOrder, strArtist) - VALUES (?, ?, ?, ?, ?) - """ -update_song_artist_obj = [ "{ArtistId}","{SongId}",1,"{Index}","{Name}" - ] -update_song_album = """ INSERT OR REPLACE INTO albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, - strTitle, iDuration) - VALUES (?, ?, ?, ?, ?) - """ -update_song_album_obj = [ "{SongId}","{AlbumId}","{Index}","{Title}","{Runtime}" - ] -update_song_rating = """ UPDATE song - SET iTimesPlayed = ?, lastplayed = ?, rating = ? - WHERE idSong = ? - """ -update_song_rating_obj = [ "{PlayCount}","{DatePlayed}","{Rating}","{KodiId}" - ] -update_genre_album = """ INSERT OR REPLACE INTO album_genre(idGenre, idAlbum) - VALUES (?, ?) - """ -update_genre_song = """ INSERT OR REPLACE INTO song_genre(idGenre, idSong) - VALUES (?, ?) - """ -update_genre_song_obj = [ "{SongId}","{Genres}","song" - ] - - - -delete_genres_album = """ DELETE FROM album_genre - WHERE idAlbum = ? - """ -delete_genres_song = """ DELETE FROM song_genre - WHERE idSong = ? - """ -delete_artist = """ DELETE FROM artist - WHERE idArtist = ? - """ -delete_album = """ DELETE FROM album - WHERE idAlbum = ? - """ -delete_song = """ DELETE FROM song - WHERE idSong = ? - """ -get_version = """ SELECT idVersion - FROM version - """ -update_versiontag = """ INSERT OR REPLACE INTO versiontagscan(idVersion, iNeedsScan) - VALUES (?, 0) +create_artist = """ SELECT coalesce(max(idArtist), 1) + FROM artist + """ +create_album = """ SELECT coalesce(max(idAlbum), 0) + FROM album + """ +create_song = """ SELECT coalesce(max(idSong), 0) + FROM song + """ +create_genre = """ SELECT coalesce(max(idGenre), 0) + FROM genre + """ + + +get_artist = """ SELECT idArtist, strArtist + FROM artist + WHERE strMusicBrainzArtistID = ? + """ +get_artist_obj = ["{ArtistId}", "{Name}", "{UniqueId}"] +get_artist_by_name = """ SELECT idArtist + FROM artist + WHERE strArtist = ? + COLLATE NOCASE + """ +get_artist_by_id = """ SELECT * + FROM artist + WHERE idArtist = ? + """ +get_artist_by_id_obj = ["{ArtistId}"] +get_album_by_id = """ SELECT * + FROM album + WHERE idAlbum = ? + """ +get_album_by_id_obj = ["{AlbumId}"] +get_song_by_id = """ SELECT * + FROM song + WHERE idSong = ? + """ +get_song_by_id_obj = ["{SongId}"] +get_album = """ SELECT idAlbum + FROM album + WHERE strMusicBrainzAlbumID = ? + """ +get_album_obj = ["{AlbumId}", "{Title}", "{UniqueId}", "{Artists}", "album"] +get_album_by_name = """ SELECT idAlbum, strArtists + FROM album + WHERE strAlbum = ? + """ +get_album_by_name72 = """ SELECT idAlbum, strArtistDisp + FROM album + WHERE strAlbum = ? + """ +get_album_artist = """ SELECT strArtists + FROM album + WHERE idAlbum = ? + """ +get_album_artist72 = """ SELECT strArtistDisp + FROM album + WHERE idAlbum = ? + """ +get_album_artist_obj = ["{AlbumId}", "{strAlbumArtists}"] +get_genre = """ SELECT idGenre + FROM genre + WHERE strGenre = ? + COLLATE NOCASE + """ +get_total_episodes = """ SELECT totalCount + FROM tvshowcounts + WHERE idShow = ? + """ + + +add_artist = """ INSERT INTO artist(idArtist, strArtist, strMusicBrainzArtistID) + VALUES (?, ?, ?) + """ +add_album = """ INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType) + VALUES (?, ?, ?, ?) + """ +add_album72 = """ INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType, bScrapedMBID) + VALUES (?, ?, ?, ?, 1) + """ +add_single = """ INSERT INTO album(idAlbum, strGenres, iYear, strReleaseType) + VALUES (?, ?, ?, ?) + """ +add_single_obj = ["{AlbumId}", "{Genre}", "{Year}", "single"] +add_song = """ INSERT INTO song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, + iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed, + rating, comment, dateAdded) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_song72 = """ INSERT INTO song(idSong, idAlbum, idPath, strArtistDisp, strGenres, strTitle, iTrack, + iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed, + rating, comment, dateAdded) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """ +add_song_obj = ["{SongId}", "{AlbumId}", "{PathId}", "{Artists}", "{Genre}", "{Title}", "{Index}", + "{Runtime}", "{Year}", "{Filename}", "{UniqueId}", "{PlayCount}", "{DatePlayed}", "{Rating}", + "{Comment}", "{DateAdded}"] +add_genre = """ INSERT INTO genre(idGenre, strGenre) + VALUES (?, ?) + """ +add_genres_obj = ["{AlbumId}", "{Genres}", "album"] + + +update_path = """ UPDATE path + SET strPath = ? + WHERE idPath = ? + """ +update_path_obj = ["{Path}", "{PathId}"] +update_role = """ INSERT OR REPLACE INTO role(idRole, strRole) + VALUES (?, ?) + """ +update_role_obj = [1, "Composer"] +update_artist_name = """ UPDATE artist + SET strArtist = ? + WHERE idArtist = ? + """ +update_artist_name_obj = ["{Name}", "{ArtistId}"] +update_artist = """ UPDATE artist + SET strGenres = ?, strBiography = ?, strImage = ?, strFanart = ?, lastScraped = ? + WHERE idArtist = ? + """ +update_link = """ INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist) + VALUES (?, ?, ?) + """ +update_link_obj = ["{ArtistId}", "{AlbumId}", "{Name}"] +update_discography = """ INSERT OR REPLACE INTO discography(idArtist, strAlbum, strYear) + VALUES (?, ?, ?) + """ +update_discography_obj = ["{ArtistId}", "{Title}", "{Year}"] +update_album = """ UPDATE album + SET strArtists = ?, iYear = ?, strGenres = ?, strReview = ?, strImage = ?, + iUserrating = ?, lastScraped = ?, strReleaseType = ? + WHERE idAlbum = ? + """ +update_album72 = """ UPDATE album + SET strArtistDisp = ?, iYear = ?, strGenres = ?, strReview = ?, strImage = ?, + iUserrating = ?, lastScraped = ?, bScrapedMBID = 1, strReleaseType = ? + WHERE idAlbum = ? + """ +update_album_obj = ["{Artists}", "{Year}", "{Genre}", "{Bio}", "{Thumb}", "{Rating}", "{LastScraped}", "album", "{AlbumId}"] +update_album_artist = """ UPDATE album + SET strArtists = ? + WHERE idAlbum = ? + """ +update_album_artist72 = """ UPDATE album + SET strArtistDisp = ? + WHERE idAlbum = ? + """ +update_song = """ UPDATE song + SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?, + iDuration = ?, iYear = ?, strFilename = ?, iTimesPlayed = ?, lastplayed = ?, + rating = ?, comment = ?, dateAdded = ? + WHERE idSong = ? + """ +update_song72 = """ UPDATE song + SET idAlbum = ?, strArtistDisp = ?, strGenres = ?, strTitle = ?, iTrack = ?, + iDuration = ?, iYear = ?, strFilename = ?, iTimesPlayed = ?, lastplayed = ?, + rating = ?, comment = ?, dateAdded = ? + WHERE idSong = ? + """ +update_song_obj = ["{AlbumId}", "{Artists}", "{Genre}", "{Title}", "{Index}", "{Runtime}", "{Year}", + "{Filename}", "{PlayCount}", "{DatePlayed}", "{Rating}", "{Comment}", + "{DateAdded}", "{SongId}"] +update_song_artist = """ INSERT OR REPLACE INTO song_artist(idArtist, idSong, idRole, iOrder, strArtist) + VALUES (?, ?, ?, ?, ?) + """ +update_song_artist_obj = ["{ArtistId}", "{SongId}", 1, "{Index}", "{Name}"] +update_song_album = """ INSERT OR REPLACE INTO albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, + strTitle, iDuration) + VALUES (?, ?, ?, ?, ?) + """ +update_song_album_obj = ["{SongId}", "{AlbumId}", "{Index}", "{Title}", "{Runtime}"] +update_song_rating = """ UPDATE song + SET iTimesPlayed = ?, lastplayed = ?, rating = ? + WHERE idSong = ? + """ +update_song_rating_obj = ["{PlayCount}", "{DatePlayed}", "{Rating}", "{KodiId}"] +update_genre_album = """ INSERT OR REPLACE INTO album_genre(idGenre, idAlbum) + VALUES (?, ?) + """ +update_genre_song = """ INSERT OR REPLACE INTO song_genre(idGenre, idSong) + VALUES (?, ?) + """ +update_genre_song_obj = ["{SongId}", "{Genres}", "song"] + + +delete_genres_album = """ DELETE FROM album_genre + WHERE idAlbum = ? + """ +delete_genres_song = """ DELETE FROM song_genre + WHERE idSong = ? + """ +delete_artist = """ DELETE FROM artist + WHERE idArtist = ? + """ +delete_album = """ DELETE FROM album + WHERE idAlbum = ? + """ +delete_song = """ DELETE FROM song + WHERE idSong = ? + """ +get_version = """ SELECT idVersion + FROM version + """ +update_versiontag = """ INSERT OR REPLACE INTO versiontagscan(idVersion, iNeedsScan) + VALUES (?, 0) + """ +get_versiontagcount = """ SELECT COUNT(*) + FROM versiontagscan """ -get_versiontagcount = """ SELECT COUNT(*) - FROM versiontagscan - """ \ No newline at end of file diff --git a/resources/lib/objects/kodi/queries_texture.py b/resources/lib/objects/kodi/queries_texture.py index 8f2235f8..4255767a 100644 --- a/resources/lib/objects/kodi/queries_texture.py +++ b/resources/lib/objects/kodi/queries_texture.py @@ -1,11 +1,10 @@ -get_cache = """ SELECT cachedurl - FROM texture - WHERE url = ? - """ +get_cache = """ SELECT cachedurl + FROM texture + WHERE url = ? + """ - -delete_cache = """ DELETE FROM texture - WHERE url = ? - """ +delete_cache = """ DELETE FROM texture + WHERE url = ? + """ diff --git a/resources/lib/objects/kodi/tvshows.py b/resources/lib/objects/kodi/tvshows.py index 35ee64c1..4d620e87 100644 --- a/resources/lib/objects/kodi/tvshows.py +++ b/resources/lib/objects/kodi/tvshows.py @@ -9,14 +9,13 @@ from kodi import Kodi ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## class TVShows(Kodi): - def __init__(self, cursor): self.cursor = cursor @@ -24,7 +23,7 @@ class TVShows(Kodi): def create_entry_unique_id(self): self.cursor.execute(QU.create_unique_id) - + return self.cursor.fetchone()[0] + 1 def create_entry_rating(self): @@ -39,12 +38,12 @@ class TVShows(Kodi): def create_entry_season(self): self.cursor.execute(QU.create_season) - + return self.cursor.fetchone()[0] + 1 def create_entry_episode(self): self.cursor.execute(QU.create_episode) - + return self.cursor.fetchone()[0] + 1 def get(self, *args): @@ -69,7 +68,7 @@ class TVShows(Kodi): try: self.cursor.execute(QU.get_rating, args) - + return self.cursor.fetchone()[0] except TypeError: return @@ -93,7 +92,7 @@ class TVShows(Kodi): try: self.cursor.execute(QU.get_unique_id, args) - + return self.cursor.fetchone()[0] except TypeError: return diff --git a/resources/lib/objects/movies.py b/resources/lib/objects/movies.py index 37701d1f..6ea50008 100644 --- a/resources/lib/objects/movies.py +++ b/resources/lib/objects/movies.py @@ -14,7 +14,7 @@ from helper import api, catch, stop, validate, jellyfin_item, library_check, val ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -103,13 +103,11 @@ class Movies(KodiDb): obj['Tags'] = tags - if update: self.movie_update(obj) else: self.movie_add(obj) - self.update_path(*values(obj, QU.update_path_movie_obj)) self.update_file(*values(obj, QU.update_file_obj)) self.add_tags(*values(obj, QU.add_tags_movie_obj)) @@ -192,7 +190,6 @@ class Movies(KodiDb): } obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params)) - @stop() @jellyfin_item() def boxset(self, item, e_item): diff --git a/resources/lib/objects/music.py b/resources/lib/objects/music.py index 6ab02e86..54e6318a 100644 --- a/resources/lib/objects/music.py +++ b/resources/lib/objects/music.py @@ -14,7 +14,7 @@ from helper import api, catch, stop, validate, jellyfin_item, values, library_ch ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -77,13 +77,11 @@ class Music(KodiDb): if obj['Backdrops']: obj['Backdrops'] = "<fanart>%s</fanart>" % obj['Backdrops'][0] - if update: self.artist_update(obj) else: self.artist_add(obj) - self.update(obj['Genre'], obj['Bio'], obj['Thumb'], obj['Backdrops'], obj['LastScraped'], obj['ArtistId']) self.artwork.add(obj['Artwork'], obj['ArtistId'], "artist") self.item_ids.append(obj['Id']) @@ -106,7 +104,6 @@ class Music(KodiDb): self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj)) LOG.info("UPDATE artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id']) - @stop() @jellyfin_item() def album(self, item, e_item): @@ -144,13 +141,11 @@ class Music(KodiDb): if obj['Thumb']: obj['Thumb'] = "<thumb>%s</thumb>" % obj['Thumb'] - if update: self.album_update(obj) else: self.album_add(obj) - self.artist_link(obj) self.artist_discography(obj) self.update_album(*values(obj, QU.update_album_obj)) @@ -217,7 +212,6 @@ class Music(KodiDb): self.link(*values(temp_obj, QU.update_link_obj)) self.item_ids.append(temp_obj['Id']) - @stop() @jellyfin_item() def song(self, item, e_item): @@ -269,15 +263,13 @@ class Music(KodiDb): if obj['Disc'] != 1: obj['Index'] = obj['Disc'] * 2 ** 16 + obj['Index'] - if update: self.song_update(obj) else: self.song_add(obj) - self.link_song_album(*values(obj, QU.update_song_album_obj)) - self.add_role(*values(obj, QU.update_role_obj)) # defaultt role + self.add_role(*values(obj, QU.update_role_obj)) # defaultt role self.song_artist_link(obj) self.song_artist_discography(obj) @@ -415,7 +407,6 @@ class Music(KodiDb): obj['AlbumId'] = self.create_entry_album() self.add_single(*values(obj, QU.add_single_obj)) - @stop() @jellyfin_item() def userdata(self, item, e_item): diff --git a/resources/lib/objects/musicvideos.py b/resources/lib/objects/musicvideos.py index dfd0ff4b..679ac231 100644 --- a/resources/lib/objects/musicvideos.py +++ b/resources/lib/objects/musicvideos.py @@ -14,7 +14,7 @@ from helper import api, catch, stop, validate, library_check, jellyfin_item, val ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -114,13 +114,11 @@ class MusicVideos(KodiDb): obj['Tags'] = tags - if update: self.musicvideo_update(obj) else: self.musicvideo_add(obj) - self.update_path(*values(obj, QU.update_path_mvideo_obj)) self.update_file(*values(obj, QU.update_file_obj)) self.add_tags(*values(obj, QU.add_tags_mvideo_obj)) @@ -176,7 +174,6 @@ class MusicVideos(KodiDb): } obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params)) - @stop() @jellyfin_item() def userdata(self, item, e_item): @@ -185,7 +182,7 @@ class MusicVideos(KodiDb): Poster with progress bar ''' server_data = self.server.auth.get_server_info(self.server.auth.server_id) - server_address = self.server.auth.get_server_address(server_data, server_data['LastConnectionMode']) + server_address = self.server.auth.get_server_address(server_data, server_data['LastConnectionMode']) API = api.API(item, server_address) obj = self.objects.map(item, 'MusicVideoUserData') diff --git a/resources/lib/objects/obj.py b/resources/lib/objects/obj.py index 16b0a34e..ac1a7aa2 100644 --- a/resources/lib/objects/obj.py +++ b/resources/lib/objects/obj.py @@ -8,7 +8,7 @@ import os ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -44,7 +44,7 @@ class Objects(object): "$": lead the key name with $. Only one key value can be requested per element. ":": indicates it's a list of elements [], i.e. MediaSources/0/MediaStreams:?$Name MediaStreams is a list. - "/": indicates where to go directly + "/": indicates where to go directly ''' self.mapped_item = {} @@ -145,7 +145,7 @@ class Objects(object): result = False for key, value in filters.iteritems(): - + inverse = False if value.startswith('!'): diff --git a/resources/lib/objects/tvshows.py b/resources/lib/objects/tvshows.py index ce6103e5..92ff9cce 100644 --- a/resources/lib/objects/tvshows.py +++ b/resources/lib/objects/tvshows.py @@ -16,7 +16,7 @@ from helper import api, catch, stop, validate, jellyfin_item, library_check, set ################################################################################################## -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################## @@ -76,7 +76,6 @@ class TVShows(KodiDb): update = False LOG.info("ShowId %s missing from kodi. repairing the entry.", obj['ShowId']) - obj['Path'] = API.get_file_path(obj['Path']) obj['LibraryId'] = library['Id'] obj['LibraryName'] = library['Name'] @@ -107,13 +106,11 @@ class TVShows(KodiDb): obj['Tags'] = tags - if update: self.tvshow_update(obj) else: self.tvshow_add(obj) - self.link(*values(obj, QU.update_tvshow_link_obj)) self.update_path(*values(obj, QU.update_path_tvshow_obj)) self.add_tags(*values(obj, QU.add_tags_tvshow_obj)) @@ -161,10 +158,10 @@ class TVShows(KodiDb): ''' Add object to kodi. ''' - obj['RatingId'] = self.create_entry_rating() + obj['RatingId'] = self.create_entry_rating() self.add_ratings(*values(obj, QU.add_rating_tvshow_obj)) - obj['Unique'] = self.create_entry_unique_id() + obj['Unique'] = self.create_entry_unique_id() self.add_unique_id(*values(obj, QU.add_unique_id_tvshow_obj)) obj['TopPathId'] = self.add_path(obj['TopLevel']) @@ -180,10 +177,10 @@ class TVShows(KodiDb): ''' Update object to kodi. ''' - obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_unique_id_tvshow_obj)) + obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_unique_id_tvshow_obj)) self.update_ratings(*values(obj, QU.update_rating_tvshow_obj)) - obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_tvshow_obj)) + obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_tvshow_obj)) self.update_unique_id(*values(obj, QU.update_unique_id_tvshow_obj)) self.update(*values(obj, QU.update_tvshow_obj)) @@ -209,7 +206,6 @@ class TVShows(KodiDb): obj['TopLevel'] = "plugin://plugin.video.jellyfin/" obj['Path'] = "%s%s/" % (obj['TopLevel'], obj['Id']) - @stop() def season(self, item, show_id=None): @@ -244,7 +240,6 @@ class TVShows(KodiDb): self.artwork.add(obj['Artwork'], obj['SeasonId'], "season") LOG.info("UPDATE season [%s/%s] %s: %s", obj['ShowId'], obj['SeasonId'], obj['Title'] or obj['Index'], obj['Id']) - @stop() @jellyfin_item() def episode(self, item, e_item): @@ -286,7 +281,6 @@ class TVShows(KodiDb): update = False LOG.info("EpisodeId %s missing from kodi. repairing the entry.", obj['EpisodeId']) - obj['Path'] = API.get_file_path(obj['Path']) obj['Index'] = obj['Index'] or -1 obj['Writers'] = " / ".join(obj['Writers'] or []) @@ -319,7 +313,7 @@ class TVShows(KodiDb): if obj['AirsAfterSeason']: obj['AirsBeforeSeason'] = obj['AirsAfterSeason'] - obj['AirsBeforeEpisode'] = 4096 # Kodi default number for afterseason ordering + obj['AirsBeforeEpisode'] = 4096 # Kodi default number for afterseason ordering if obj['MultiEpisode']: obj['Title'] = "| %02d | %s" % (obj['MultiEpisode'], obj['Title']) @@ -329,13 +323,11 @@ class TVShows(KodiDb): obj['SeasonId'] = self.get_season(*values(obj, QU.get_season_episode_obj)) - if update: self.episode_update(obj) else: self.episode_add(obj) - self.update_path(*values(obj, QU.update_path_episode_obj)) self.update_file(*values(obj, QU.update_file_obj)) self.add_people(*values(obj, QU.add_people_episode_obj)) @@ -359,10 +351,10 @@ class TVShows(KodiDb): ''' Add object to kodi. ''' - obj['RatingId'] = self.create_entry_rating() + obj['RatingId'] = self.create_entry_rating() self.add_ratings(*values(obj, QU.add_rating_episode_obj)) - obj['Unique'] = self.create_entry_unique_id() + obj['Unique'] = self.create_entry_unique_id() self.add_unique_id(*values(obj, QU.add_unique_id_episode_obj)) obj['PathId'] = self.add_path(*values(obj, QU.add_path_obj)) @@ -387,7 +379,7 @@ class TVShows(KodiDb): obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_rating_episode_obj)) self.update_ratings(*values(obj, QU.update_rating_episode_obj)) - obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_episode_obj)) + obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_episode_obj)) self.update_unique_id(*values(obj, QU.update_unique_id_episode_obj)) self.update_episode(*values(obj, QU.update_episode_obj)) @@ -440,7 +432,6 @@ class TVShows(KodiDb): return True - @stop() @jellyfin_item() def userdata(self, item, e_item): diff --git a/resources/lib/objects/utils.py b/resources/lib/objects/utils.py index 4048a118..c0bfadcf 100644 --- a/resources/lib/objects/utils.py +++ b/resources/lib/objects/utils.py @@ -8,7 +8,7 @@ from helper import JSONRPC ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# diff --git a/resources/lib/player.py b/resources/lib/player.py index a6204be4..2158a991 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -15,7 +15,7 @@ from jellyfin import Jellyfin ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -326,7 +326,7 @@ class Player(xbmc.Player): try: played = float(item['CurrentPosition'] * 10000000) / int(item['Runtime']) * 100 - except ZeroDivisionError: # Runtime is 0. + except ZeroDivisionError: # Runtime is 0. played = 0 if played > 2.0 and not self.up_next: @@ -338,7 +338,6 @@ class Player(xbmc.Player): return - result = JSONRPC('Application.GetProperties').execute({'properties': ["volume", "muted"]}) result = result.get('result', {}) item['Volume'] = result.get('volume') @@ -415,7 +414,6 @@ class Player(xbmc.Player): LOG.info("<[ transcode/%s ]", item['Id']) item['Server'].jellyfin.close_transcode(item['DeviceId']) - path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/temp/").decode('utf-8') if xbmcvfs.exists(path): diff --git a/resources/lib/setup.py b/resources/lib/setup.py index 001161ad..311ee3c3 100644 --- a/resources/lib/setup.py +++ b/resources/lib/setup.py @@ -10,7 +10,7 @@ from helper import _, settings, dialog, JSONRPC, compare_version ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# @@ -43,7 +43,7 @@ class Setup(object): settings('enableTextureCache.bool', False) dialog("ok", heading="{jellyfin}", line1=_(33103)) - + return result = get_setting.execute({'setting': "services.webserverport"}) diff --git a/resources/lib/views.py b/resources/lib/views.py index b746bb4a..6920d4f7 100644 --- a/resources/lib/views.py +++ b/resources/lib/views.py @@ -19,7 +19,7 @@ from jellyfin import Jellyfin ################################################################################################# -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) NODES = { 'tvshows': [ ('all', None), @@ -70,7 +70,7 @@ DYNNODES = { ('FirstLetter', _(33171)), ('Genres', _(135)), ('Random', _(30229)), - #('Recommended', _(30230)) + # ('Recommended', _(30230)) ], 'musicvideos': [ ('all', None), @@ -136,6 +136,7 @@ def verify_kodi_defaults(): if not xbmcvfs.exists(playlist_path): xbmcvfs.mkdirs(playlist_path) + class Views(object): sync = None @@ -246,7 +247,7 @@ class Views(object): temp_view['Media'] = media self.add_playlist(playlist_path, temp_view, True) self.add_nodes(node_path, temp_view, True) - else: # Compensate for the duplicate. + else: # Compensate for the duplicate. index += 1 else: if view['Media'] in ('movies', 'tvshows', 'musicvideos'): @@ -421,7 +422,6 @@ class Views(object): etree.SubElement(xml, 'match') etree.SubElement(xml, 'content') - label = xml.find('label') label.text = str(name) if type(name) == int else name @@ -438,7 +438,7 @@ class Views(object): rule = etree.SubElement(xml, 'rule', {'field': "tag", 'operator': "is"}) etree.SubElement(rule, 'value').text = view['Tag'] - getattr(self, 'node_' + node)(xml) # get node function based on node type + getattr(self, 'node_' + node)(xml) # get node function based on node type indent(xml) write_xml(etree.tostring(xml, 'UTF-8'), file) @@ -642,7 +642,7 @@ class Views(object): if rule.attrib['field'] == 'inprogress': break else: - etree.SubElement(root, 'rule', {'field': "inprogress", 'operator':"true"}) + etree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"}) content = root.find('content') content.text = "episodes" @@ -661,7 +661,6 @@ class Views(object): else: etree.SubElement(root, 'content').text = "episodes" - def order_media_folders(self, folders): ''' Returns a list of sorted media folders based on the Jellyfin views. @@ -704,7 +703,7 @@ class Views(object): for library in (libraries or []): view = {'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2]} - if library[0] in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]: # Synced libraries + if library[0] in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]: # Synced libraries if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'): @@ -718,7 +717,7 @@ class Views(object): temp_view['Name'] = "%s (%s)" % (view['Name'], _(media)) self.window_node(index, temp_view, *node) self.window_wnode(windex, temp_view, *node) - else: # Add one to compensate for the duplicate. + else: # Add one to compensate for the duplicate. index += 1 windex += 1 else: @@ -734,7 +733,7 @@ class Views(object): elif view['Media'] == 'music': self.window_node(index, view, 'music') - else: # Dynamic entry + else: # Dynamic entry if view['Media'] in ('homevideos', 'books', 'playlists'): self.window_wnode(windex, view, 'browse') windex += 1 @@ -781,7 +780,7 @@ class Views(object): if node in ('all', 'music'): window_prop = "Jellyfin.nodes.%s" % index - window('%s.index' % window_prop, path.replace('all.xml', "")) # dir + window('%s.index' % window_prop, path.replace('all.xml', "")) # dir window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.content' % window_prop, path) @@ -833,7 +832,7 @@ class Views(object): if node == 'all': window_prop = "Jellyfin.wnodes.%s" % index - window('%s.index' % window_prop, path.replace('all.xml', "")) # dir + window('%s.index' % window_prop, path.replace('all.xml', "")) # dir window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.content' % window_prop, path) @@ -909,16 +908,16 @@ class Views(object): total = int(window((name or 'Jellyfin.nodes') + '.total') or 0) props = [ - "index","id","path","artwork","title","content","type" - "inprogress.content","inprogress.title", - "inprogress.content","inprogress.path", - "nextepisodes.title","nextepisodes.content", - "nextepisodes.path","unwatched.title", - "unwatched.content","unwatched.path", - "recent.title","recent.content","recent.path", - "recentepisodes.title","recentepisodes.content", - "recentepisodes.path","inprogressepisodes.title", - "inprogressepisodes.content","inprogressepisodes.path" + "index", "id", "path", "artwork", "title", "content", "type" + "inprogress.content", "inprogress.title", + "inprogress.content", "inprogress.path", + "nextepisodes.title", "nextepisodes.content", + "nextepisodes.path", "unwatched.title", + "unwatched.content", "unwatched.path", + "recent.title", "recent.content", "recent.path", + "recentepisodes.title", "recentepisodes.content", + "recentepisodes.path", "inprogressepisodes.title", + "inprogressepisodes.content", "inprogressepisodes.path" ] for i in range(total): for prop in props: diff --git a/resources/lib/webservice.py b/resources/lib/webservice.py index 3eb51da4..dc68e69a 100644 --- a/resources/lib/webservice.py +++ b/resources/lib/webservice.py @@ -13,10 +13,11 @@ import xbmc ################################################################################################# PORT = 57578 -LOG = logging.getLogger("JELLYFIN."+__name__) +LOG = logging.getLogger("JELLYFIN." + __name__) ################################################################################################# + class WebService(threading.Thread): ''' Run a webservice to trigger playback. @@ -127,7 +128,7 @@ class requestHandler(BaseHTTPServer.BaseHTTPRequestHandler): % (params.get('Id'), params.get('KodiId'), params.get('Name'), params.get('transcode') or False)) self.send_response(200) - self.send_header('Content-type','text/html') + self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(path) @@ -142,4 +143,3 @@ class requestHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.send_error(500, "Exception occurred: %s" % error) return -