diff --git a/resources/lib/context_entry.py b/resources/lib/context_entry.py index c6507fec..d6ab7e1a 100644 --- a/resources/lib/context_entry.py +++ b/resources/lib/context_entry.py @@ -5,14 +5,10 @@ from logging import getLogger import xbmc import xbmcgui -from . import context -from . import plexdb_functions as plexdb -from . import utils -from . import plex_functions as PF from .plex_api import API -from . import playqueue as PQ -from . import variables as v -from . import state +from .plex_db import PlexDB +from . import context, plex_functions as PF, playqueue as PQ +from . import utils, variables as v, state ############################################################################### @@ -74,12 +70,10 @@ class ContextMenu(object): def _get_plex_id(kodi_id, kodi_type): plex_id = xbmc.getInfoLabel('ListItem.Property(plexid)') or None if not plex_id and kodi_id and kodi_type: - with plexdb.Get_Plex_DB() as plexcursor: - item = plexcursor.getItem_byKodiId(kodi_id, kodi_type) - try: - plex_id = item[0] - except TypeError: - LOG.info('Could not get the Plex id for context menu') + with PlexDB() as plexdb: + item = plexdb.item_by_kodi_id(kodi_id, kodi_type) + if item: + plex_id = item['plex_id'] return plex_id def _select_menu(self): diff --git a/resources/lib/itemtypes/common.py b/resources/lib/itemtypes/common.py index a640d07f..b9b53046 100644 --- a/resources/lib/itemtypes/common.py +++ b/resources/lib/itemtypes/common.py @@ -4,12 +4,10 @@ from __future__ import absolute_import, division, unicode_literals from logging import getLogger from ntpath import dirname -from . import artwork -from . import utils -from . import plexdb_functions as plexdb -from . import kodidb_functions as kodidb -from .plex_api import API -from . import variables as v +from ..plex_api import API +from ..plex_db import PlexDB +from .. import kodidb_functions as kodidb +from .. import artwork, utils, variables as v LOG = getLogger('PLEX.itemtypes.common') @@ -41,14 +39,14 @@ class ItemBase(object): Input: kodiType: optional argument; e.g. 'video' or 'music' """ - def __init__(self, last_sync, plex_db=None, kodi_db=None): + def __init__(self, last_sync, plexdb=None, kodi_db=None): self.last_sync = last_sync self.artwork = artwork.Artwork() self.plexconn = None - self.plexcursor = plex_db.cursor if plex_db else None + self.plexcursor = plexdb.cursor if plexdb else None self.kodiconn = None self.kodicursor = kodi_db.cursor if kodi_db else None - self.plex_db = plex_db + self.plexdb = plexdb self.kodi_db = kodi_db def __enter__(self): @@ -59,7 +57,7 @@ class ItemBase(object): self.plexcursor = self.plexconn.cursor() self.kodiconn = utils.kodi_sql('video') self.kodicursor = self.kodiconn.cursor() - self.plex_db = plexdb.Plex_DB_Functions(self.plexcursor) + self.plexdb = PlexDB(self.plexcursor) self.kodi_db = kodidb.KodiDBMethods(self.kodicursor) return self @@ -92,7 +90,7 @@ class ItemBase(object): for mediaitem in xml: api = API(mediaitem) # Get key and db entry on the Kodi db side - db_item = self.plex_db.getItem_byId(api.plex_id()) + db_item = self.plexdb.getItem_byId(api.plex_id()) try: fileid = db_item[1] except TypeError: diff --git a/resources/lib/itemtypes/movies.py b/resources/lib/itemtypes/movies.py index 4bfe8fcc..c5fa467d 100644 --- a/resources/lib/itemtypes/movies.py +++ b/resources/lib/itemtypes/movies.py @@ -27,7 +27,7 @@ class Movie(ItemBase): if not plex_id: LOG.error('Cannot parse XML data for movie: %s', xml.attrib) return - movie = self.plex_db.getItem_byId(plex_id) + movie = self.plexdb.getItem_byId(plex_id) try: kodi_id = movie[0] old_kodi_fileid = movie[1] @@ -204,20 +204,20 @@ class Movie(ItemBase): playcount, dateplayed, v.PLEX_TYPE_MOVIE) - self.plex_db.add_movie(plex_id=plex_id, - checksum=api.checksum(), - section_id=section_id, - kodi_id=kodi_id, - kodi_fileid=file_id, - kodi_pathid=kodi_pathid, - last_sync=self.last_sync) + self.plexdb.add_movie(plex_id=plex_id, + checksum=api.checksum(), + section_id=section_id, + kodi_id=kodi_id, + kodi_fileid=file_id, + kodi_pathid=kodi_pathid, + last_sync=self.last_sync) def remove(self, plex_id): """ Remove a movie with all references and all orphaned associated entries from the Kodi DB """ - movie = self.plex_db.movie(plex_id) + movie = self.plexdb.movie(plex_id) try: kodi_id = movie[3] file_id = movie[4] @@ -229,7 +229,7 @@ class Movie(ItemBase): plex_id) return # Remove the plex reference - self.plex_db.remove(plex_id, v.PLEX_TYPE_MOVIE) + self.plexdb.remove(plex_id, v.PLEX_TYPE_MOVIE) # Remove artwork self.artwork.delete_artwork(kodi_id, kodi_type, self.self.kodicursor) set_id = self.kodi_db.get_set_id(kodi_id) diff --git a/resources/lib/itemtypes/music.py b/resources/lib/itemtypes/music.py index f1bccd00..de1e3c6b 100644 --- a/resources/lib/itemtypes/music.py +++ b/resources/lib/itemtypes/music.py @@ -16,7 +16,7 @@ class MusicMixin(object): Remove the entire music object, including all associated entries from both Plex and Kodi DBs """ - db_item = self.plex_db.item_by_id(plex_id, plex_type) + db_item = self.plexdb.item_by_id(plex_id, plex_type) if not db_item: LOG.debug('Cannot delete plex_id %s - not found in DB', plex_id) return @@ -24,45 +24,45 @@ class MusicMixin(object): db_item['plex_type'], plex_id, db_item['kodi_id']) # Remove the plex reference - self.plex_db.remove(plex_id, db_item['plex_type']) + self.plexdb.remove(plex_id, db_item['plex_type']) # SONG ##### if db_item['plex_type'] == v.PLEX_TYPE_SONG: # Delete episode, verify season and tvshow self.remove_song(db_item['kodi_id'], db_item['kodi_pathid']) # Album verification - if not self.plex_db.album_has_songs(db_item['album_id']): + if not self.plexdb.album_has_songs(db_item['album_id']): # No episode left for this season - so delete the season self.remove_album(db_item['parent_id']) - self.plex_db.remove(db_item['album_id'], v.PLEX_TYPE_ALBUM) + self.plexdb.remove(db_item['album_id'], v.PLEX_TYPE_ALBUM) # Artist verification - if (not self.plex_db.artist_has_albums(db_item['artist_id']) and - not self.plex_db.artist_has_songs(db_item['artist_id'])): + if (not self.plexdb.artist_has_albums(db_item['artist_id']) and + not self.plexdb.artist_has_songs(db_item['artist_id'])): self.remove_artist(db_item['grandparent_id']) - self.plex_db.remove(db_item['artist_id'], v.PLEX_TYPE_ARTIST) + self.plexdb.remove(db_item['artist_id'], v.PLEX_TYPE_ARTIST) # ALBUM ##### elif db_item['plex_type'] == v.PLEX_TYPE_ALBUM: # Remove episodes, season, verify tvshow - for song in self.plex_db.song_by_album(db_item['plex_id']): + for song in self.plexdb.song_by_album(db_item['plex_id']): self.remove_song(song['kodi_id'], song['kodi_pathid']) - self.plex_db.remove(song['plex_id'], v.PLEX_TYPE_SONG) + self.plexdb.remove(song['plex_id'], v.PLEX_TYPE_SONG) # Remove the album self.remove_album(db_item['kodi_id']) # Show verification - if (not self.plex_db.artist_has_albums(db_item['album_id']) and - not self.plex_db.artist_has_songs(db_item['album_id'])): + if (not self.plexdb.artist_has_albums(db_item['album_id']) and + not self.plexdb.artist_has_songs(db_item['album_id'])): # There's no other season or episode left, delete the show self.remove_artist(db_item['parent_id']) - self.plex_db.remove(db_item['artist_id'], v.KODI_TYPE_ARTIST) + self.plexdb.remove(db_item['artist_id'], v.KODI_TYPE_ARTIST) # ARTIST ##### elif db_item['plex_type'] == v.PLEX_TYPE_ARTIST: # Remove songs, albums and the artist himself - for song in self.plex_db.song_by_artist(db_item['plex_id']): + for song in self.plexdb.song_by_artist(db_item['plex_id']): self.remove_song(song['kodi_id'], song['kodi_pathid']) - self.plex_db.remove(song['plex_id'], v.PLEX_TYPE_SONG) - for album in self.plex_db.album_by_artist(db_item['plex_id']): + self.plexdb.remove(song['plex_id'], v.PLEX_TYPE_SONG) + for album in self.plexdb.album_by_artist(db_item['plex_id']): self.remove_album(album['kodi_id']) - self.plex_db.remove(album['plex_id'], v.PLEX_TYPE_ALBUM) + self.plexdb.remove(album['plex_id'], v.PLEX_TYPE_ALBUM) self.remove_artist(db_item['kodi_id']) LOG.debug('Deleted %s %s from all databases', @@ -141,7 +141,7 @@ class Artist(ItemBase, MusicMixin): LOG.error('Cannot process artist %s', xml.attrib) return LOG.debug('Adding artist with plex_id %s', plex_id) - db_item = self.plex_db.artist(plex_id) + db_item = self.plexdb.artist(plex_id) if not db_item: update_item = False else: @@ -196,11 +196,11 @@ class Artist(ItemBase, MusicMixin): kodi_id, v.KODI_TYPE_ARTIST, self.kodicursor) - self.plex_db.add_artist(plex_id, - api.checksum(), - section_id, - kodi_id, - self.last_sync) + self.plexdb.add_artist(plex_id, + api.checksum(), + section_id, + kodi_id, + self.last_sync) class Album(ItemBase, MusicMixin): @@ -218,7 +218,7 @@ class Album(ItemBase, MusicMixin): LOG.error('Error processing album: %s', xml.attrib) return LOG.debug('Adding album with plex_id %s', plex_id) - db_item = self.plex_db.album(plex_id) + db_item = self.plexdb.album(plex_id) if db_item: update_item = True kodi_id = db_item['kodi_id'] @@ -324,7 +324,7 @@ class Album(ItemBase, MusicMixin): artist_id = None if parent_id is not None: try: - artist_id = self.plex_db.getItem_byId(parent_id)[0] + artist_id = self.plexdb.getItem_byId(parent_id)[0] except TypeError: LOG.info('Artist %s does not yet exist in Plex DB', parent_id) artist = PF.GetPlexMetadata(parent_id) @@ -334,13 +334,13 @@ class Album(ItemBase, MusicMixin): LOG.error('Could not get artist xml for %s', parent_id) else: self.add_updateArtist(artist[0]) - plex_dbartist = self.plex_db.getItem_byId(parent_id) + plexdbartist = self.plexdb.getItem_byId(parent_id) try: - artist_id = plex_dbartist[0] + artist_id = plexdbartist[0] except TypeError: LOG.error('Adding artist failed for %s', parent_id) # Update plex reference with the artist_id - self.plex_db.updateParentId(plex_id, artist_id) + self.plexdb.updateParentId(plex_id, artist_id) # Add artist to album query = ''' INSERT OR REPLACE INTO album_artist( @@ -373,7 +373,7 @@ class Album(ItemBase, MusicMixin): # Add all children - all tracks if scan_children: context = Song(self.last_sync, - plex_db=self.plex_db, + plexdb=self.plexdb, kodi_db=self.kodi_db) for song in children: context.add_update(song, @@ -383,13 +383,13 @@ class Album(ItemBase, MusicMixin): genres=genres, genre=genre, compilation=compilation) - self.plex_db.add_album(plex_id, - api.checksum(), - section_id, - artist_id, - parent_id, - kodi_id, - self.last_sync) + self.plexdb.add_album(plex_id, + api.checksum(), + section_id, + artist_id, + parent_id, + kodi_id, + self.last_sync) class Song(ItemBase, MusicMixin): @@ -405,7 +405,7 @@ class Song(ItemBase, MusicMixin): LOG.error('Error processing song: %s', xml.attrib) return LOG.debug('Adding song with plex_id %s', plex_id) - db_item = self.plex_db.song(plex_id) + db_item = self.plexdb.song(plex_id) if db_item: update_item = True kodi_id = db_item['kodi_id'] @@ -564,7 +564,7 @@ class Song(ItemBase, MusicMixin): # Add path kodi_pathid = self.kodi_db.add_music_path(path, hash_string="123") # Get the album - album = self.plex_db.album(api.parent_plex_id()) + album = self.plexdb.album(api.parent_plex_id()) if album: parent_id = album['kodi_id'] else: @@ -579,14 +579,14 @@ class Song(ItemBase, MusicMixin): LOG.error('Could not download album %s,', album_id) return context = Album(self.last_sync, - plex_db=self.plex_db, + plexdb=self.plexdb, kodi_db=self.kodi_db) context.add_update(album_xml[0], section_name=section_name, section_id=section_id, children=[xml], scan_children=False) - album = self.plex_db.album(album_id) + album = self.plexdb.album(album_id) if album: parent_id = album['kodi_id'] LOG.debug("Found parent_id for album: %s", parent_id) @@ -708,7 +708,7 @@ class Song(ItemBase, MusicMixin): # Link song to artists artist_name = api.grandparent_title() artist_id = api.grandparent_id() - artist = self.plex_db.artist(artist_id) + artist = self.plexdb.artist(artist_id) if artist: grandparent_id = artist['kodi_id'] else: @@ -718,13 +718,13 @@ class Song(ItemBase, MusicMixin): LOG.error('Error getting artist, abort') return context = Artist(self.last_sync, - plex_db=self.plex_db, + plexdb=self.plexdb, kodi_db=self.kodi_db) context.add_update(artist_xml[0], section_name=section_name, section_id=section_id, children=None) - artist = self.plex_db.artist(artist_id) + artist = self.plexdb.artist(artist_id) if not artist: LOG.error('Could not add artist %s for song %s', artist_name, plex_id) @@ -758,13 +758,13 @@ class Song(ItemBase, MusicMixin): v.KODI_TYPE_ALBUM, self.kodicursor) # Create the reference in plex table - self.plex_db.add_song(plex_id, - api.checksum(), - section_id, - artist_id, - grandparent_id, - album_id, - parent_id, - kodi_id, - kodi_pathid, - self.last_sync) + self.plexdb.add_song(plex_id, + api.checksum(), + section_id, + artist_id, + grandparent_id, + album_id, + parent_id, + kodi_id, + kodi_pathid, + self.last_sync) diff --git a/resources/lib/itemtypes/tvshows.py b/resources/lib/itemtypes/tvshows.py index ef38691d..308849dc 100644 --- a/resources/lib/itemtypes/tvshows.py +++ b/resources/lib/itemtypes/tvshows.py @@ -16,7 +16,7 @@ class TvShowMixin(object): Remove the entire TV shows object (show, season or episode) including all associated entries from the Kodi DB. """ - db_item = self.plex_db.item_by_id(plex_id, plex_type) + db_item = self.plexdb.item_by_id(plex_id, plex_type) if not db_item: LOG.debug('Cannot delete plex_id %s - not found in DB', plex_id) return @@ -24,47 +24,47 @@ class TvShowMixin(object): db_item['plex_type'], plex_id, db_item['kodi_id']) # Remove the plex reference - self.plex_db.remove(plex_id, db_item['plex_type']) + self.plexdb.remove(plex_id, db_item['plex_type']) # EPISODE ##### if db_item['plex_type'] == v.PLEX_TYPE_EPISODE: # Delete episode, verify season and tvshow self.remove_episode(db_item['kodi_id'], db_item['kodi_fileid']) # Season verification - if not self.plex_db.season_has_episodes(db_item['season_id']): + if not self.plexdb.season_has_episodes(db_item['season_id']): # No episode left for this season - so delete the season self.remove_season(db_item['parent_id']) - self.plex_db.remove(db_item['season_id'], v.PLEX_TYPE_SEASON) + self.plexdb.remove(db_item['season_id'], v.PLEX_TYPE_SEASON) # Show verification - if (not self.plex_db.show_has_seasons(db_item['show_id']) and - not self.plex_db.show_has_episodes(db_item['show_id'])): + if (not self.plexdb.show_has_seasons(db_item['show_id']) and + not self.plexdb.show_has_episodes(db_item['show_id'])): # No seasons for show left - so delete entire show self.remove_show(db_item['grandparent_id']) - self.plex_db.remove(db_item['show_id'], v.PLEX_TYPE_SHOW) + self.plexdb.remove(db_item['show_id'], v.PLEX_TYPE_SHOW) # SEASON ##### elif db_item['plex_type'] == v.PLEX_TYPE_SEASON: # Remove episodes, season, verify tvshow - for episode in self.plex_db.episode_by_season(db_item['plex_id']): + for episode in self.plexdb.episode_by_season(db_item['plex_id']): self.remove_episode(episode['kodi_id'], episode['kodi_fileid']) - self.plex_db.remove(episode['plex_id'], v.PLEX_TYPE_EPISODE) + self.plexdb.remove(episode['plex_id'], v.PLEX_TYPE_EPISODE) # Remove season self.remove_season(db_item['kodi_id']) # Show verification - if (not self.plex_db.show_has_seasons(db_item['show_id']) and - not self.plex_db.show_has_episodes(db_item['show_id'])): + if (not self.plexdb.show_has_seasons(db_item['show_id']) and + not self.plexdb.show_has_episodes(db_item['show_id'])): # There's no other season or episode left, delete the show self.remove_show(db_item['parent_id']) - self.plex_db.remove(db_item['show_id'], v.KODI_TYPE_SHOW) + self.plexdb.remove(db_item['show_id'], v.KODI_TYPE_SHOW) # TVSHOW ##### elif db_item['plex_type'] == v.PLEX_TYPE_SHOW: # Remove episodes, seasons and the tvshow itself - for episode in self.plex_db.episode_by_show(db_item['plex_id']): + for episode in self.plexdb.episode_by_show(db_item['plex_id']): self.remove_episode(episode['kodi_id'], episode['kodi_fileid']) - self.plex_db.remove(episode['plex_id'], v.PLEX_TYPE_EPISODE) - for season in self.plex_db.season_by_show(db_item['plex_id']): + self.plexdb.remove(episode['plex_id'], v.PLEX_TYPE_EPISODE) + for season in self.plexdb.season_by_show(db_item['plex_id']): self.remove_season(season['kodi_id']) - self.plex_db.remove(season['plex_id'], v.PLEX_TYPE_SEASON) + self.plexdb.remove(season['plex_id'], v.PLEX_TYPE_SEASON) self.remove_show(db_item['kodi_id']) LOG.debug('Deleted %s %s from all databases', @@ -131,7 +131,7 @@ class Show(ItemBase, TvShowMixin): if not plex_id: LOG.error("Cannot parse XML data for TV show: %s", xml.attrib) return - show = self.plex_db.show(plex_id) + show = self.plexdb.show(plex_id) try: kodi_id = show[3] kodi_pathid = show[4] @@ -266,12 +266,12 @@ class Show(ItemBase, TvShowMixin): tags = [section_name] tags.extend([i for _, i in api.collection_list()]) self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_SHOW, tags) - self.plex_db.add_show(plex_id=plex_id, - checksum=api.checksum(), - section_id=section_id, - kodi_id=kodi_id, - kodi_pathid=kodi_pathid, - last_sync=self.last_sync) + self.plexdb.add_show(plex_id=plex_id, + checksum=api.checksum(), + section_id=section_id, + kodi_id=kodi_id, + kodi_pathid=kodi_pathid, + last_sync=self.last_sync) class Season(ItemBase, TvShowMixin): @@ -288,7 +288,7 @@ class Season(ItemBase, TvShowMixin): xml.attrib) return show_id = api.parent_plex_id() - show = self.plex_db.show(show_id) + show = self.plexdb.show(show_id) try: parent_id = show[3] except TypeError: @@ -300,13 +300,13 @@ class Season(ItemBase, TvShowMixin): kodi_id, v.KODI_TYPE_SEASON, self.kodicursor) - self.plex_db.add_season(plex_id=plex_id, - checksum=api.checksum(), - section_id=section_id, - show_id=show_id, - parent_id=parent_id, - kodi_id=kodi_id, - last_sync=self.last_sync) + self.plexdb.add_season(plex_id=plex_id, + checksum=api.checksum(), + section_id=section_id, + show_id=show_id, + parent_id=parent_id, + kodi_id=kodi_id, + last_sync=self.last_sync) class Episode(ItemBase, TvShowMixin): @@ -323,7 +323,7 @@ class Episode(ItemBase, TvShowMixin): LOG.error('Error getting plex_id for episode, skipping: %s', xml.attrib) return - entry = self.plex_db.item_by_id(plex_id) + entry = self.plexdb.item_by_id(plex_id) try: kodi_id = entry[0] old_kodi_fileid = entry[1] @@ -358,7 +358,7 @@ class Episode(ItemBase, TvShowMixin): airs_before_season = "-1" airs_before_episode = "-1" - show = self.plex_db.show(show_id) + show = self.plexdb.show(show_id) try: grandparent_id = show[3] except TypeError: @@ -506,14 +506,14 @@ class Episode(ItemBase, TvShowMixin): userdata['PlayCount'], userdata['LastPlayedDate'], None) # Do send None - 2nd entry - self.plex_db.add_episode(plex_id=plex_id, - checksum=api.checksum(), - section_id=section_id, - show_id=show_id, - grandparent_id=grandparent_id, - season_id=season_id, - parent_id=parent_id, - kodi_id=kodi_id, - kodi_fileid=kodi_fileid, - kodi_pathid=kodi_pathid, - last_sync=self.last_sync) + self.plexdb.add_episode(plex_id=plex_id, + checksum=api.checksum(), + section_id=section_id, + show_id=show_id, + grandparent_id=grandparent_id, + season_id=season_id, + parent_id=parent_id, + kodi_id=kodi_id, + kodi_fileid=kodi_fileid, + kodi_pathid=kodi_pathid, + last_sync=self.last_sync) diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 24e9712e..4c1e4d61 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -11,7 +11,7 @@ import copy import xbmc from xbmcgui import Window -from . import plexdb_functions as plexdb +from .plex_db import PlexDB from . import kodidb_functions as kodidb from . import utils from . import plex_functions as PF @@ -181,25 +181,23 @@ class KodiMonitor(xbmc.Monitor): if playcount is None or item is None: return try: - kodiid = item['id'] - item_type = item['type'] + kodi_id = item['id'] + kodi_type = item['type'] except (KeyError, TypeError): LOG.info("Item is invalid for playstate update.") return # Send notification to the server. - with plexdb.Get_Plex_DB() as plexcur: - plex_dbitem = plexcur.getItem_byKodiId(kodiid, item_type) - try: - itemid = plex_dbitem[0] - except TypeError: - LOG.error("Could not find itemid in plex database for a " + with PlexDB() as plexdb: + db_item = plexdb.item_by_kodi_id(kodi_id, kodi_type) + if not db_item: + LOG.error("Could not find plex_id in plex database for a " "video library update") else: # notify the server if playcount > 0: - PF.scrobble(itemid, 'watched') + PF.scrobble(db_item['plex_id'], 'watched') else: - PF.scrobble(itemid, 'unwatched') + PF.scrobble(db_item['plex_id'], 'unwatched') elif method == "VideoLibrary.OnRemove": pass elif method == "System.OnSleep": @@ -306,14 +304,11 @@ class KodiMonitor(xbmc.Monitor): if not kodi_id and kodi_type and path: kodi_id, _ = kodidb.kodiid_from_filename(path, kodi_type) if kodi_id: - with plexdb.Get_Plex_DB() as plex_db: - plex_dbitem = plex_db.getItem_byKodiId(kodi_id, kodi_type) - try: - plex_id = plex_dbitem[0] - plex_type = plex_dbitem[2] - except TypeError: - # No plex id, hence item not in the library. E.g. clips - pass + with PlexDB() as plexdb: + db_item = plexdb.item_by_kodi_id(kodi_id, kodi_type) + if db_item: + plex_id = db_item['plex_id'] + plex_type = db_item['plex_type'] return plex_id, plex_type @staticmethod @@ -542,8 +537,8 @@ def _record_playstate(status, ended): if not status['plex_id']: LOG.debug('No Plex id found to record playstate for status %s', status) return - with plexdb.Get_Plex_DB() as plex_db: - kodi_db_item = plex_db.getItem_byId(status['plex_id']) + with PlexDB() as plexdb: + kodi_db_item = plexdb.item_by_id(status['plex_id'], status['plex_type']) if kodi_db_item is None: # Item not (yet) in Kodi library LOG.debug('No playstate update due to Plex id not found: %s', status) diff --git a/resources/lib/library_sync/sections.py b/resources/lib/library_sync/sections.py index 17ec9078..1f6019ae 100644 --- a/resources/lib/library_sync/sections.py +++ b/resources/lib/library_sync/sections.py @@ -6,7 +6,8 @@ import copy from . import common, videonodes from ..utils import cast -from .. import plexdb_functions as plexdb, kodidb_functions as kodidb +from ..plex_db import PlexDB +from .. import kodidb_functions as kodidb from .. import itemtypes from .. import PlexFunctions as PF, music, utils, state, variables as v @@ -54,15 +55,15 @@ def sync_from_pms(): VNODES.clearProperties() - with plexdb.PlexDB() as plex_db: + with PlexDB() as plexdb: # Backup old sections to delete them later, if needed (at the end # of this method, only unused sections will be left in old_sections) - old_sections = [plex_db.section_ids()] + old_sections = [plexdb.section_ids()] with kodidb.GetKodiDB('video') as kodi_db: for section in sections: _process_section(section, kodi_db, - plex_db, + plexdb, sorted_sections, old_sections, totalnodes) @@ -71,14 +72,14 @@ def sync_from_pms(): # Section has been deleted on the PMS delete_sections(old_sections) # update sections for all: - with plexdb.PlexDB() as plex_db: - SECTIONS = [plex_db.section_infos()] + with plexdb.PlexDB() as plexdb: + SECTIONS = [plexdb.section_infos()] utils.window('Plex.nodes.total', str(totalnodes)) LOG.info("Finished processing library sections: %s", SECTIONS) return True -def _process_section(section_xml, kodi_db, plex_db, sorted_sections, +def _process_section(section_xml, kodi_db, plexdb, sorted_sections, old_sections, totalnodes): folder = section_xml.attrib plex_type = cast(unicode, folder['type']) @@ -95,7 +96,7 @@ def _process_section(section_xml, kodi_db, plex_db, sorted_sections, # Prevent duplicate for playlists of the same type playlists = PLAYLISTS[plex_type] # Get current media folders from plex database - section = plex_db.section(section_id) + section = plexdb.section(section_id) try: current_sectionname = section[1] current_sectiontype = section[2] @@ -118,7 +119,7 @@ def _process_section(section_xml, kodi_db, plex_db, sorted_sections, nodes.append(section_name) totalnodes += 1 # Add view to plex database - plex_db.add_section(section_id, section_name, plex_type, tagid) + plexdb.add_section(section_id, section_name, plex_type, tagid) else: LOG.info('Found library section id %s, name %s, type %s, tagid %s', section_id, current_sectionname, current_sectiontype, @@ -137,12 +138,12 @@ def _process_section(section_xml, kodi_db, plex_db, sorted_sections, tagid = kodi_db.create_tag(section_name) # Update view with new info - plex_db.add_section(section_id, + plexdb.add_section(section_id, section_name, plex_type, tagid) - if plex_db.section_id_by_name(current_sectionname) is None: + if plexdb.section_id_by_name(current_sectionname) is None: # The tag could be a combined view. Ensure there's # no other tags with the same name before deleting # playlist. @@ -176,7 +177,7 @@ def _process_section(section_xml, kodi_db, plex_db, sorted_sections, nodes.append(section_name) totalnodes += 1 # Update items with new tag - for item in plex_db.kodi_id_by_section(section_id): + for item in plexdb.kodi_id_by_section(section_id): # Remove the "s" from viewtype for tags kodi_db.update_tag( current_tagid, tagid, item[0], current_sectiontype[:-1]) @@ -212,30 +213,30 @@ def delete_sections(old_sections): sound=False) video_library_update = False music_library_update = False - with plexdb.PlexDB() as plex_db: - old_sections = [plex_db.section(x) for x in old_sections] + with PlexDB() as plexdb: + old_sections = [plexdb.section(x) for x in old_sections] LOG.info("Removing entire Plex library sections: %s", old_sections) with kodidb.GetKodiDB() as kodi_db: for section in old_sections: if section[2] == v.KODI_TYPE_MOVIE: video_library_update = True - context = itemtypes.Movie(plex_db=plex_db, + context = itemtypes.Movie(plexdb=plexdb, kodi_db=kodi_db) elif section[2] == v.KODI_TYPE_SHOW: video_library_update = True - context = itemtypes.Show(plex_db=plex_db, + context = itemtypes.Show(plexdb=plexdb, kodi_db=kodi_db) elif section[2] == v.KODI_TYPE_ARTIST: music_library_update = True - context = itemtypes.Artist(plex_db=plex_db, + context = itemtypes.Artist(plexdb=plexdb, kodi_db=kodi_db) elif section[2] == v.KODI_TYPE_PHOTO: # not synced - plex_db.remove_section(section[0]) + plexdb.remove_section(section[0]) continue - for plex_id in plex_db.plexid_by_section(section[0]): + for plex_id in plexdb.plexid_by_section(section[0]): context.remove(plex_id) # Only remove Plex entry if we've removed all items first - plex_db.remove_section(section[0]) + plexdb.remove_section(section[0]) common.update_kodi_library(video=video_library_update, music=music_library_update) diff --git a/resources/lib/playback.py b/resources/lib/playback.py index f14dfd2b..1980865a 100644 --- a/resources/lib/playback.py +++ b/resources/lib/playback.py @@ -9,10 +9,10 @@ from threading import Thread from xbmc import Player, sleep from .plex_api import API +from .plex_db import PlexDB from . import plex_functions as PF from . import utils from .downloadutils import DownloadUtils as DU -from . import plexdb_functions as plexdb from . import kodidb_functions as kodidb from . import playlist_func as PL from . import playqueue as PQ @@ -313,10 +313,10 @@ def _prep_playlist_stack(xml): api.plex_type() not in (v.PLEX_TYPE_CLIP, v.PLEX_TYPE_EPISODE)): # If user chose to play via PMS or force transcode, do not # use the item path stored in the Kodi DB - with plexdb.Get_Plex_DB() as plex_db: - plex_dbitem = plex_db.getItem_byId(api.plex_id()) - kodi_id = plex_dbitem[0] if plex_dbitem else None - kodi_type = plex_dbitem[4] if plex_dbitem else None + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(api.plex_id(), api.plex_type()) + kodi_id = db_item['kodi_id'] if db_item else None + kodi_type = db_item['kodi_type'] if db_item else None else: # We will never store clips (trailers) in the Kodi DB. # Also set kodi_id to None for playback via PMS, so that we're @@ -425,9 +425,9 @@ def _conclude_playback(playqueue, pos): state.RESUME_PLAYBACK = False if (item.offset is None and item.plex_type not in (v.PLEX_TYPE_SONG, v.PLEX_TYPE_CLIP)): - with plexdb.Get_Plex_DB() as plex_db: - plex_dbitem = plex_db.getItem_byId(item.plex_id) - file_id = plex_dbitem[1] if plex_dbitem else None + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(item.plex_id, item.plex_type) + file_id = db_item['kodi_fileid'] if db_item else None with kodidb.GetKodiDB('video') as kodi_db: item.offset = kodi_db.get_resume(file_id) LOG.info('Resuming playback at %s', item.offset) diff --git a/resources/lib/playlist_func.py b/resources/lib/playlist_func.py index 8a2a1e7a..253c7d49 100644 --- a/resources/lib/playlist_func.py +++ b/resources/lib/playlist_func.py @@ -9,8 +9,8 @@ import urllib from urlparse import parse_qsl, urlsplit from .plex_api import API +from .plex_db import PlexDB from . import plex_functions as PF -from . import plexdb_functions as plexdb from . import kodidb_functions as kodidb from .downloadutils import DownloadUtils as DU from . import utils @@ -254,15 +254,12 @@ def playlist_item_from_kodi(kodi_item): item.kodi_id = kodi_item.get('id') item.kodi_type = kodi_item.get('type') if item.kodi_id: - with plexdb.Get_Plex_DB() as plex_db: - plex_dbitem = plex_db.getItem_byKodiId(kodi_item['id'], - kodi_item['type']) - try: - item.plex_id = plex_dbitem[0] - item.plex_type = plex_dbitem[2] - item.plex_uuid = plex_dbitem[0] # we dont need the uuid yet :-) - except TypeError: - pass + with PlexDB() as plexdb: + db_item = plexdb.item_by_kodi_id(kodi_item['id'], kodi_item['type']) + if db_item: + item.plex_id = db_item['plex_id'] + item.plex_type = db_item['plex_type'] + item.plex_uuid = db_item['plex_id'] # we dont need the uuid yet :-) item.file = kodi_item.get('file') if item.plex_id is None and item.file is not None: query = dict(parse_qsl(urlsplit(item.file).query)) @@ -334,13 +331,13 @@ def playlist_item_from_plex(plex_id): """ item = Playlist_Item() item.plex_id = plex_id - with plexdb.Get_Plex_DB() as plex_db: - plex_dbitem = plex_db.getItem_byId(plex_id) - try: - item.plex_type = plex_dbitem[5] - item.kodi_id = plex_dbitem[0] - item.kodi_type = plex_dbitem[4] - except (TypeError, IndexError): + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(plex_id) + if db_item: + item.plex_type = db_item['plex_type'] + item.kodi_id = db_item['kodi_id'] + item.kodi_type = db_item['kodi_type'] + else: raise KeyError('Could not find plex_id %s in database' % plex_id) item.plex_uuid = plex_id item.uri = ('library://%s/item/library%%2Fmetadata%%2F%s' % @@ -366,12 +363,11 @@ def playlist_item_from_xml(xml_video_element, kodi_id=None, kodi_type=None): item.kodi_id = kodi_id item.kodi_type = kodi_type elif item.plex_id is not None and item.plex_type != v.PLEX_TYPE_CLIP: - with plexdb.Get_Plex_DB() as plex_db: - db_element = plex_db.getItem_byId(item.plex_id) - try: - item.kodi_id, item.kodi_type = db_element[0], db_element[4] - except TypeError: - pass + with PlexDB() as plexdb: + db_element = plexdb.item_by_id(item.plex_id) + if db_element: + item.kodi_id = db_element['kodi_id'] + item.kodi_type = db_element['kodi_type'] item.guid = api.guid_html_escaped() item.playcount = api.viewcount() item.offset = api.resume_point() diff --git a/resources/lib/playlists/db.py b/resources/lib/playlists/db.py index 464948b5..96074fad 100644 --- a/resources/lib/playlists/db.py +++ b/resources/lib/playlists/db.py @@ -8,9 +8,8 @@ from __future__ import absolute_import, division, unicode_literals from logging import getLogger from .common import Playlist, PlaylistError - +from ..plex_db import PlexDB from .. import kodidb_functions as kodidb -from .. import plexdb_functions as plexdb from .. import path_ops, utils, variables as v ############################################################################### LOG = getLogger('PLEX.playlists.db') @@ -22,16 +21,16 @@ def plex_playlist_ids(): """ Returns a list of all Plex ids of the playlists already in our DB """ - with plexdb.Get_Plex_DB() as plex_db: - return plex_db.plex_ids_all_playlists() + with PlexDB() as plexdb: + return [plexdb.playlist_ids()] def kodi_playlist_paths(): """ Returns a list of all Kodi playlist paths of the playlists already synced """ - with plexdb.Get_Plex_DB() as plex_db: - return plex_db.all_kodi_playlist_paths() + with PlexDB() as plexdb: + return [plexdb.kodi_playlist_paths()] def update_playlist(playlist, delete=False): @@ -41,11 +40,11 @@ def update_playlist(playlist, delete=False): Pass delete=True to delete the playlist entry """ - with plexdb.Get_Plex_DB() as plex_db: + with PlexDB() as plexdb: if delete: - plex_db.delete_playlist_entry(playlist) + plexdb.delete_playlist(playlist) else: - plex_db.insert_playlist_entry(playlist) + plexdb.add_playlist(playlist) def get_playlist(path=None, kodi_hash=None, plex_id=None): @@ -55,10 +54,8 @@ def get_playlist(path=None, kodi_hash=None, plex_id=None): content. """ playlist = Playlist() - with plexdb.Get_Plex_DB() as plex_db: - playlist = plex_db.retrieve_playlist(playlist, - plex_id, - path, kodi_hash) + with PlexDB() as plexdb: + playlist = plexdb.playlist(playlist, plex_id, path, kodi_hash) return playlist @@ -95,8 +92,8 @@ def m3u_to_plex_ids(playlist): entry, db_type=playlist.kodi_type) if not kodi_id: continue - with plexdb.Get_Plex_DB() as plex_db: - plex_id = plex_db.getItem_byKodiId(kodi_id, kodi_type) + with PlexDB() as plexdb: + plex_id = plexdb.item_by_kodi_id(kodi_id, kodi_type) if plex_id: plex_ids.append(plex_id[0]) return plex_ids diff --git a/resources/lib/plex_api.py b/resources/lib/plex_api.py index e83a4f03..d3df72e5 100644 --- a/resources/lib/plex_api.py +++ b/resources/lib/plex_api.py @@ -37,13 +37,13 @@ from urllib import urlencode, unquote, quote from urlparse import parse_qsl from xbmcgui import ListItem +from .plex_db import PlexDB from .utils import cast from .downloadutils import DownloadUtils as DU from . import clientinfo from . import utils from . import path_ops from . import plex_functions as PF -from . import plexdb_functions as plexdb from . import kodidb_functions as kodidb from . import variables as v from . import state @@ -943,23 +943,19 @@ class API(object): artworks[kodi_artwork] = art if not full_artwork: return artworks - with plexdb.Get_Plex_DB() as plex_db: - try: - season_id = plex_db.getItem_byId(self.plex_id())[3] - except TypeError: + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(self.plex_id(), + v.PLEX_TYPE_EPISODE) + if db_item: + season_id = db_item['parent_id'] + show_id = db_item['grandparent_id'] + else: return artworks # Grab artwork from the season with kodidb.GetKodiDB('video') as kodi_db: season_art = kodi_db.get_art(season_id, v.KODI_TYPE_SEASON) for kodi_art in season_art: artworks['season.%s' % kodi_art] = season_art[kodi_art] - # Get the show id - with plexdb.Get_Plex_DB() as plex_db: - try: - show_id = plex_db.getItem_byKodiId(season_id, - v.KODI_TYPE_SEASON)[1] - except TypeError: - return artworks # Grab more artwork from the show with kodidb.GetKodiDB('video') as kodi_db: show_art = kodi_db.get_art(show_id, v.KODI_TYPE_SHOW) @@ -1651,11 +1647,10 @@ class API(object): plex_id = self.plex_id() listitem.setProperty('plexid', plex_id) - with plexdb.Get_Plex_DB() as plex_db: - kodi_id = plex_db.getItem_byId(plex_id) - if kodi_id: - kodi_id = kodi_id[0] - metadata['dbid'] = kodi_id + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(plex_id, self.plex_type()) + if db_item: + metadata['dbid'] = db_item['kodi_id'] metadata['title'] = title # Expensive operation listitem.setInfo('video', infoLabels=metadata) @@ -1716,11 +1711,10 @@ class API(object): plex_id = self.plex_id() listitem.setProperty('plexid', plex_id) if v.KODIVERSION >= 18: - with plexdb.Get_Plex_DB() as plex_db: - kodi_id = plex_db.getItem_byId(plex_id) - if kodi_id: - kodi_id = kodi_id[0] - metadata['dbid'] = kodi_id + with PlexDB() as plexdb: + db_item = plexdb.item_by_id(plex_id, self.plex_type()) + if db_item: + metadata['dbid'] = db_item['kodi_id'] listitem.setInfo('music', infoLabels=metadata) return listitem diff --git a/resources/lib/plex_db/__init__.py b/resources/lib/plex_db/__init__.py index 4236b898..3339efdd 100644 --- a/resources/lib/plex_db/__init__.py +++ b/resources/lib/plex_db/__init__.py @@ -6,7 +6,8 @@ from .common import PlexDBBase, initialize, wipe from .tvshows import TVShows from .movies import Movies from .music import Music +from .playlists import Playlists -class PlexDB(PlexDBBase, TVShows, Movies, Music): +class PlexDB(PlexDBBase, TVShows, Movies, Music, Playlists): pass diff --git a/resources/lib/plex_db/common.py b/resources/lib/plex_db/common.py index 0d9a84ef..78589e11 100644 --- a/resources/lib/plex_db/common.py +++ b/resources/lib/plex_db/common.py @@ -4,6 +4,15 @@ from __future__ import absolute_import, division, unicode_literals from . import utils, variables as v +SUPPORTED_KODI_TYPES = ( + v.KODI_TYPE_MOVIE, + v.KODI_TYPE_SHOW, + v.KODI_TYPE_SEASON, + v.KODI_TYPE_EPISODE, + v.KODI_TYPE_ARTIST, + v.KODI_TYPE_ALBUM, + v.KODI_TYPE_SONG) + class PlexDBBase(object): """ @@ -24,14 +33,8 @@ class PlexDBBase(object): def item_by_id(self, plex_id, plex_type=None): """ - Returns the following dict or None if not found - { - plex_id - plex_type - kodi_id - kodi_type - } - for plex_id. Supply with the correct plex_type to speed up lookup + Returns the item for plex_id or None. + Supply with the correct plex_type to speed up lookup """ answ = None if plex_type == v.PLEX_TYPE_MOVIE: @@ -64,6 +67,17 @@ class PlexDBBase(object): break return answ + def item_by_kodi_id(self, kodi_id, kodi_type): + """ + """ + if kodi_type not in SUPPORTED_KODI_TYPES: + return + query = ('SELECT * from %s WHERE kodi_id = ? LIMIT 1' + % v.PLEX_TYPE_FROM_KODI_TYPE[kodi_type]) + self.cursor.execute(query, (kodi_id, )) + method = getattr(self, 'entry_to_%s' % v.PLEX_TYPE_FROM_KODI_TYPE[kodi_type]) + return method(self.cursor.fetchone()) + def section_ids(self): """ Returns an iterator for section Plex ids for all sections diff --git a/resources/lib/plex_db/playlists.py b/resources/lib/plex_db/playlists.py new file mode 100644 index 00000000..6fdd22a5 --- /dev/null +++ b/resources/lib/plex_db/playlists.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, unicode_literals +from .. import variables as v + + +class Playlists(object): + def playlist_ids(self): + """ + Returns an iterator of all Plex ids of playlists. + """ + self.cursor.execute('SELECT plex_id FROM playlists') + return (x[0] for x in self.cursor) + + def kodi_playlist_paths(self): + """ + Returns an iterator of all Kodi playlist paths. + """ + self.cursor.execute('SELECT kodi_path FROM playlists') + return (x[0] for x in self.cursor) + + def delete_playlist(self, playlist): + """ + Removes the entry for playlist [Playqueue_Object] from the Plex + playlists table. + Be sure to either set playlist.id or playlist.kodi_path + """ + if playlist.plex_id: + query = 'DELETE FROM playlists WHERE plex_id = ?' + var = playlist.plex_id + elif playlist.kodi_path: + query = 'DELETE FROM playlists WHERE kodi_path = ?' + var = playlist.kodi_path + else: + raise RuntimeError('Cannot delete playlist: %s' % playlist) + self.cursor.execute(query, (var, )) + + def add_playlist(self, playlist): + """ + Inserts or modifies an existing entry in the Plex playlists table. + """ + query = ''' + INSERT OR REPLACE INTO playlists( + plex_id, + plex_name, + plex_updatedat, + kodi_path, + kodi_type, + kodi_hash) + VALUES (?, ?, ?, ?, ?, ?) + ''' + self.cursor.execute( + query, + (playlist.plex_id, + playlist.plex_name, + playlist.plex_updatedat, + playlist.kodi_path, + playlist.kodi_type, + playlist.kodi_hash)) + + def playlist(self, playlist, plex_id=None, path=None, kodi_hash=None): + """ + Returns a complete Playlist (empty one passed in via playlist) + for the entry with plex_id OR kodi_hash OR kodi_path. + Returns None if not found + """ + query = 'SELECT * FROM playlists WHERE %s = ? LIMIT 1' + if plex_id: + query = query % 'plex_id' + var = plex_id + elif kodi_hash: + query = query % 'kodi_hash' + var = kodi_hash + else: + query = query % 'kodi_path' + var = path + self.cursor.execute(query, (var, )) + answ = self.cursor.fetchone() + if not answ: + return + playlist.plex_id = answ[0] + playlist.plex_name = answ[1] + playlist.plex_updatedat = answ[2] + playlist.kodi_path = answ[3] + playlist.kodi_type = answ[4] + playlist.kodi_hash = answ[5] + return playlist diff --git a/resources/lib/plexdb_functions.py b/resources/lib/plexdb_functions.py deleted file mode 100644 index e1a0d1a4..00000000 --- a/resources/lib/plexdb_functions.py +++ /dev/null @@ -1,462 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import absolute_import, division, unicode_literals -from . import utils -from . import variables as v - -############################################################################### - - -class Get_Plex_DB(): - """ - Usage: with Get_Plex_DB() as plex_db: - plex_db.do_something() - - On exiting "with" (no matter what), commits get automatically committed - and the db gets closed - """ - def __enter__(self): - self.plexconn = utils.kodi_sql('plex') - return Plex_DB_Functions(self.plexconn.cursor()) - - def __exit__(self, type, value, traceback): - self.plexconn.commit() - self.plexconn.close() - - -class Plex_DB_Functions(): - - def __init__(self, plexcursor): - self.plexcursor = plexcursor - - def sections(self): - """ - Returns a list of section Plex ids for all sections - """ - self.plexcursor.execute('SELECT section_id FROM sections') - return [x[0] for x in self.plexcursor] - - def list_section_info(self): - """ - Returns a list of dicts for all Plex libraries: - { - 'section_id' - 'section_name' - 'plex_type' - 'kodi_tagid' - 'sync_to_kodi' - } - """ - self.plexcursor.execute('SELECT * FROM sections') - return [{'section_id': x[0], - 'section_name': x[1], - 'plex_type': x[2], - 'kodi_tagid': x[3], - 'sync_to_kodi': x[4]} for x in self.plexcursor] - - def section_by_id(self, section_id): - """ - Returns tuple (section_id, section_name, plex_type, kodi_tagid, - sync_to_kodi) for section_id - """ - self.plexcursor.execute('SELECT * FROM sections WHERE section_id = ? LIMIT 1', - (section_id, )) - return self.plexcursor.fetchone() - - def section_id_by_name(self, section_name): - """ - Returns the section_id for section_name (or None) - """ - query = ''' - SELECT section_id FROM sections - WHERE section_name = ? - LIMIT 1 - ''' - self.plexcursor.execute(query, (section_name,)) - try: - section = self.plexcursor.fetchone()[0] - except TypeError: - section = None - return section - - def add_section(self, section_id, section_name, plex_type, kodi_tagid, - sync_to_kodi=True): - """ - Appends a Plex section to the Plex sections table - sync=False: Plex library won't be synced to Kodi - """ - query = ''' - INSERT INTO sections( - section_id, section_name, plex_type, kodi_tagid, sync_to_kodi) - VALUES (?, ?, ?, ?, ?) - ''' - self.plexcursor.execute(query, - (section_id, - section_name, - plex_type, - kodi_tagid, - sync_to_kodi)) - - def update_section(self, section_name, kodi_tagid, section_id): - """ - Updates the section_id with section_name and kodi_tagid - """ - query = ''' - UPDATE sections - SET section_name = ?, kodi_tagid = ? - WHERE section_id = ? - ''' - self.plexcursor.execute(query, (section_name, kodi_tagid, section_id)) - - def remove_section(self, section_id): - self.plexcursor.execute('DELETE FROM sections WHERE section_id = ?', - (section_id, )) - - def plexid_by_section(self, section_id): - """ - Returns an iterator for the plex_id for section_id - """ - self.plexcursor.execute('SELECT plex_id FROM plex WHERE section_id = ?', - (section_id, )) - return (x[0] for x in self.plexcursor) - - def getItem_byId(self, plex_id): - """ - For plex_id, returns the tuple - (kodi_id, kodi_fileid, kodi_pathid, parent_id, kodi_type, plex_type) - - None if not found - """ - query = ''' - SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, kodi_type, - plex_type - FROM plex WHERE plex_id = ? - LIMIT 1 - ''' - self.plexcursor.execute(query, (plex_id,)) - return self.plexcursor.fetchone() - - def getItem_byWildId(self, plex_id): - """ - Returns a list of tuples (kodi_id, kodi_type) for plex_id (% appended) - """ - query = ''' - SELECT kodi_id, kodi_type - FROM plex - WHERE plex_id LIKE ? - ''' - self.plexcursor.execute(query, (plex_id + "%",)) - return self.plexcursor.fetchall() - - def kodi_id_by_section(self, section_id): - """ - Returns an iterator! Returns kodi_id for section_id - """ - self.plexcursor.execute('SELECT kodi_id FROM plex WHERE section_id = ?', - (section_id, )) - return self.plexcursor - - def getItem_byKodiId(self, kodi_id, kodi_type): - """ - Returns the tuple (plex_id, parent_id, plex_type) for kodi_id and - kodi_type - """ - query = ''' - SELECT plex_id, parent_id, plex_type - FROM plex - WHERE kodi_id = ? AND kodi_type = ? - LIMIT 1 - ''' - self.plexcursor.execute(query, (kodi_id, kodi_type,)) - return self.plexcursor.fetchone() - - def getItem_byParentId(self, parent_id, kodi_type): - """ - Returns a list of tuples (plex_id, kodi_id, kodi_fileid) for parent_id, - kodi_type - """ - query = ''' - SELECT plex_id, kodi_id, kodi_fileid - FROM plex - WHERE parent_id = ? AND kodi_type = ? - ''' - self.plexcursor.execute(query, (parent_id, kodi_type,)) - return self.plexcursor.fetchall() - - def getItemId_byParentId(self, parent_id, kodi_type): - """ - Returns the tuple (plex_id, kodi_id) for parent_id, kodi_type - """ - query = ''' - SELECT plex_id, kodi_id - FROM plex - WHERE parent_id = ? - AND kodi_type = ? - ''' - self.plexcursor.execute(query, (parent_id, kodi_type,)) - return self.plexcursor.fetchall() - - def check_plexid(self, plex_id): - """ - FAST method to check whether plex_id has already been safed in db. - Returns None if not yet in plex DB - """ - self.plexcursor.execute('SELECT plex_id FROM plex WHERE plex_id = ? LIMIT 1', - (plex_id, )) - return self.plexcursor.fetchone() - - def check_checksum(self, checksum): - """ - FAST method to check whether checksum has already been safed in db. - Returns None if not yet in plex DB - """ - self.plexcursor.execute('SELECT checksum FROM plex WHERE checksum = ? LIMIT 1', - (checksum, )) - return self.plexcursor.fetchone() - - def update_last_sync(self, plex_id, last_sync): - """ - Fast method that updates Plex table with last_sync (an int) for plex_id - """ - self.plexcursor.execute('UPDATE plex SET last_sync = ? WHERE plex_id = ?', - (last_sync, plex_id, )) - - def checksum(self, plex_type): - """ - Returns a list of tuples (plex_id, checksum) for plex_type - """ - query = ''' - SELECT plex_id, checksum - FROM plex - WHERE plex_type = ? - ''' - self.plexcursor.execute(query, (plex_type,)) - return self.plexcursor.fetchall() - - def addReference(self, plex_id, plex_type, kodi_id, kodi_type, - kodi_fileid=None, kodi_pathid=None, parent_id=None, - checksum=None, section_id=None, last_sync=None): - """ - Appends or replaces an entry into the plex table - """ - query = ''' - INSERT OR REPLACE INTO plex( - plex_id, kodi_id, kodi_fileid, kodi_pathid, plex_type, - kodi_type, parent_id, checksum, section_id, fanart_synced, - last_sync) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ''' - self.plexcursor.execute(query, (plex_id, kodi_id, kodi_fileid, - kodi_pathid, plex_type, kodi_type, - parent_id, checksum, section_id, 0, - last_sync)) - - def updateReference(self, plex_id, checksum): - """ - Updates checksum for plex_id - """ - query = "UPDATE plex SET checksum = ? WHERE plex_id = ?" - self.plexcursor.execute(query, (checksum, plex_id)) - - def updateParentId(self, plexid, parent_kodiid): - """ - Updates parent_id for plex_id - """ - query = "UPDATE plex SET parent_id = ? WHERE plex_id = ?" - self.plexcursor.execute(query, (parent_kodiid, plexid)) - - def removeItems_byParentId(self, parent_id, kodi_type): - """ - Removes all entries with parent_id and kodi_type - """ - query = ''' - DELETE FROM plex - WHERE parent_id = ? - AND kodi_type = ? - ''' - self.plexcursor.execute(query, (parent_id, kodi_type,)) - - def removeItem_byKodiId(self, kodi_id, kodi_type): - """ - Removes the one entry with kodi_id and kodi_type - """ - query = ''' - DELETE FROM plex - WHERE kodi_id = ? - AND kodi_type = ? - ''' - self.plexcursor.execute(query, (kodi_id, kodi_type,)) - - def removeItem(self, plex_id): - """ - Removes the one entry with plex_id - """ - self.plexcursor.execute('DELETE FROM plex WHERE plex_id = ?', - (plex_id,)) - - def itemsByType(self, plex_type): - """ - Returns a list of dicts for plex_type: - { - 'plex_id': plex_id - 'kodiId': kodi_id - 'kodi_type': kodi_type - 'plex_type': plex_type - } - """ - query = ''' - SELECT plex_id, kodi_id, kodi_type - FROM plex - WHERE plex_type = ? - ''' - self.plexcursor.execute(query, (plex_type, )) - result = [] - for row in self.plexcursor.fetchall(): - result.append({ - 'plex_id': row[0], - 'kodiId': row[1], - 'kodi_type': row[2], - 'plex_type': plex_type - }) - return result - - def set_fanart_synched(self, plex_id): - """ - Sets the fanart_synced flag to 1 for plex_id - """ - query = 'UPDATE plex SET fanart_synced = 1 WHERE plex_id = ?' - self.plexcursor.execute(query, (plex_id,)) - - def get_missing_fanart(self): - """ - Returns a list of {'plex_id': x, 'plex_type': y} where fanart_synced - flag is set to 0 - - This only for plex_type is either movie or TV show - """ - query = ''' - SELECT plex_id, plex_type FROM plex - WHERE fanart_synced = ? - AND (plex_type = ? OR plex_type = ?) - ''' - self.plexcursor.execute(query, - (0, v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)) - rows = self.plexcursor.fetchall() - result = [] - for row in rows: - result.append({'plex_id': row[0], - 'plex_type': row[1]}) - return result - - def plex_id_from_playlist_path(self, path): - """ - Given the Kodi playlist path [unicode], this will return the Plex id - [str] or None - """ - query = 'SELECT plex_id FROM playlists WHERE kodi_path = ? LIMIT 1' - self.plexcursor.execute(query, (path, )) - try: - plex_id = self.plexcursor.fetchone()[0] - except TypeError: - plex_id = None - return plex_id - - def plex_ids_all_playlists(self): - """ - Returns a list of all Plex ids of playlists. - """ - answ = [] - self.plexcursor.execute('SELECT plex_id FROM playlists') - for entry in self.plexcursor.fetchall(): - answ.append(entry[0]) - return answ - - def all_kodi_playlist_paths(self): - """ - Returns a list of all Kodi playlist paths. - """ - answ = [] - self.plexcursor.execute('SELECT kodi_path FROM playlists') - for entry in self.plexcursor.fetchall(): - answ.append(entry[0]) - return answ - - def retrieve_playlist(self, playlist, plex_id=None, path=None, - kodi_hash=None): - """ - Returns a complete Playlist (empty one passed in via playlist) - for the entry with plex_id OR kodi_hash OR kodi_path. - Returns None if not found - """ - query = ''' - SELECT plex_id, plex_name, plex_updatedat, kodi_path, kodi_type, - kodi_hash - FROM playlists - WHERE %s = ? - LIMIT 1 - ''' - if plex_id: - query = query % 'plex_id' - var = plex_id - elif kodi_hash: - query = query % 'kodi_hash' - var = kodi_hash - else: - query = query % 'kodi_path' - var = path - self.plexcursor.execute(query, (var, )) - answ = self.plexcursor.fetchone() - if not answ: - return - playlist.plex_id = answ[0] - playlist.plex_name = answ[1] - playlist.plex_updatedat = answ[2] - playlist.kodi_path = answ[3] - playlist.kodi_type = answ[4] - playlist.kodi_hash = answ[5] - return playlist - - def insert_playlist_entry(self, playlist): - """ - Inserts or modifies an existing entry in the Plex playlists table. - """ - query = ''' - INSERT OR REPLACE INTO playlists( - plex_id, plex_name, plex_updatedat, kodi_path, kodi_type, - kodi_hash) - VALUES (?, ?, ?, ?, ?, ?) - ''' - self.plexcursor.execute(query, - (playlist.plex_id, playlist.plex_name, - playlist.plex_updatedat, playlist.kodi_path, - playlist.kodi_type, playlist.kodi_hash)) - - def delete_playlist_entry(self, playlist): - """ - Removes the entry for playlist [Playqueue_Object] from the Plex - playlists table. - Be sure to either set playlist.id or playlist.kodi_path - """ - if playlist.plex_id: - query = 'DELETE FROM playlists WHERE plex_id = ?' - var = playlist.plex_id - elif playlist.kodi_path: - query = 'DELETE FROM playlists WHERE kodi_path = ?' - var = playlist.kodi_path - else: - raise RuntimeError('Cannot delete playlist: %s' % playlist) - self.plexcursor.execute(query, (var, )) - - -def wipe_dbs(): - """ - Completely resets the Plex database - """ - query = "SELECT name FROM sqlite_master WHERE type = 'table'" - with Get_Plex_DB() as plex_db: - plex_db.plexcursor.execute(query) - tables = plex_db.plexcursor.fetchall() - tables = [i[0] for i in tables] - for table in tables: - delete_query = 'DELETE FROM %s' % table - plex_db.plexcursor.execute(delete_query) diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 45e60820..3e3014fa 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -508,14 +508,14 @@ def wipe_database(): delete_nodes() from . import kodidb_functions kodidb_functions.wipe_dbs() - from . import plexdb_functions + from .plex_db import PlexDB # First get the paths to all synced playlists playlist_paths = [] - with plexdb_functions.Get_Plex_DB() as plex_db: - plex_db.plexcursor.execute('SELECT kodi_path FROM playlists') - for entry in plex_db.plexcursor.fetchall(): + with PlexDB() as plex_db: + plex_db.cursor.execute('SELECT kodi_path FROM playlists') + for entry in plex_db.cursor: playlist_paths.append(entry[0]) - plexdb_functions.wipe_dbs() + PlexDB.wipe() # Delete all synced playlists for path in playlist_paths: try: