Rewire llibrary sync, part 7

This commit is contained in:
croneter 2018-10-24 15:20:25 +02:00
parent f520cebf66
commit 205dc3fab8
8 changed files with 1085 additions and 595 deletions

File diff suppressed because it is too large Load diff

View file

@ -926,7 +926,6 @@ class KodiDBMethods(object):
def delete_song_from_song_artist(self, song_id): def delete_song_from_song_artist(self, song_id):
""" """
Deletes son from song_artist table and possibly orphaned roles Deletes son from song_artist table and possibly orphaned roles
Will returned an orphaned idArtist or None if not orphaned
""" """
query = ''' query = '''
SELECT idArtist, idRole FROM song_artist WHERE idSong = ? LIMIT 1 SELECT idArtist, idRole FROM song_artist WHERE idSong = ? LIMIT 1
@ -946,13 +945,6 @@ class KodiDBMethods(object):
# Delete orphaned role # Delete orphaned role
self.cursor.execute('DELETE FROM role WHERE idRole = ?', self.cursor.execute('DELETE FROM role WHERE idRole = ?',
(artist[1], )) (artist[1], ))
# Check whether we need to delete orphaned artists
query = 'SELECT idArtist FROM song_artist WHERE idArtist = ? LIMIT 1'
self.cursor.execute(query, (artist[0], ))
if self.cursor.fetchone():
return
else:
return artist[0]
def delete_album_from_discography(self, album_id): def delete_album_from_discography(self, album_id):
""" """

View file

@ -264,6 +264,12 @@ class API(object):
""" """
return cast(int, self.item.get('index')) return cast(int, self.item.get('index'))
def track_number(self):
"""
Returns the 'index' of an XML reply as int. Depicts track number.
"""
return cast(int, self.item.get('index'))
def date_created(self): def date_created(self):
""" """
Returns the date when this library item was created. Returns the date when this library item was created.
@ -486,6 +492,13 @@ class API(object):
return cast(unicode, self.item.get('titleSort', return cast(unicode, self.item.get('titleSort',
self.item.get('title','Missing Title'))) self.item.get('title','Missing Title')))
def artist_name(self):
"""
Returns the artist name for an album: first it attempts to return
'parentTitle', if that failes 'originalTitle'
"""
return self.item.get('parentTitle', self.item.get('originalTitle'))
def plot(self): def plot(self):
""" """
Returns the plot or None. Returns the plot or None.
@ -605,18 +618,16 @@ class API(object):
""" """
Returns the 'studio' or None Returns the 'studio' or None
""" """
return self.item.get('studio') return self.replace_studio(cast(unicode, self.item.get('studio')))
def music_studio_list(self): def music_studio_list(self):
""" """
Returns a list with a single entry for the studio, or an empty list Returns a list with a single entry for the studio, or an empty list
""" """
studio = [] studio = self.music_studio()
try: if studio:
studio.append(self.replace_studio(self.item.attrib['studio'])) return [studio]
except KeyError: return []
pass
return studio
@staticmethod @staticmethod
def replace_studio(studio_name): def replace_studio(studio_name):
@ -1657,23 +1668,11 @@ class API(object):
pass pass
return listitem return listitem
def track_number(self):
"""
Returns the song's track number as an int or None if not found
"""
try:
return int(self.item.get('index'))
except TypeError:
pass
def disc_number(self): def disc_number(self):
""" """
Returns the song's disc number as an int or None if not found Returns the song's disc number as an int or None if not found
""" """
try: return cast(int, self.item.get('parentIndex'))
return int(self.item.get('parentIndex'))
except TypeError:
pass
def _create_audio_listitem(self, listitem=None): def _create_audio_listitem(self, listitem=None):
""" """

View file

@ -5,7 +5,8 @@ from __future__ import absolute_import, division, unicode_literals
from .common import PlexDBBase, initialize, wipe from .common import PlexDBBase, initialize, wipe
from .tvshows import TVShows from .tvshows import TVShows
from .movies import Movies from .movies import Movies
from .music import Music
class PlexDB(PlexDBBase, TVShows, Movies): class PlexDB(PlexDBBase, TVShows, Movies, Music):
pass pass

View file

@ -64,69 +64,6 @@ class PlexDBBase(object):
break break
return answ return answ
@staticmethod
def entry_to_movie(entry):
return {
'plex_type': v.PLEX_TYPE_MOVIE,
'kodi_type': v.KODI_TYPE_MOVIE,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'kodi_id': entry[3],
'kodi_fileid': entry[4],
'kodi_pathid': entry[5],
'fanart_synced': entry[6],
'last_sync': entry[7]
}
@staticmethod
def entry_to_episode(entry):
return {
'plex_type': v.PLEX_TYPE_EPISODE,
'kodi_type': v.KODI_TYPE_EPISODE,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'show_id': entry[3],
'grandparent_id': entry[4],
'season_id': entry[5],
'parent_id': entry[6],
'kodi_id': entry[7],
'kodi_fileid': entry[8],
'kodi_pathid': entry[9],
'fanart_synced': entry[10],
'last_sync': entry[11]
}
@staticmethod
def entry_to_show(entry):
return {
'plex_type': v.PLEX_TYPE_SHOW,
'kodi_type': v.KODI_TYPE_SHOW,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'kodi_id': entry[3],
'kodi_pathid': entry[4],
'fanart_synced': entry[5],
'last_sync': entry[6]
}
@staticmethod
def entry_to_season(entry):
return {
'plex_type': v.PLEX_TYPE_SEASON,
'kodi_type': v.KODI_TYPE_SEASON,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'show_id': entry[3],
'parent_id': entry[4],
'kodi_id': entry[5],
'fanart_synced': entry[6],
'last_sync': entry[7]
}
def section_ids(self): def section_ids(self):
""" """
Returns an iterator for section Plex ids for all sections Returns an iterator for section Plex ids for all sections
@ -307,7 +244,6 @@ def initialize():
checksum INTEGER UNIQUE, checksum INTEGER UNIQUE,
section_id INTEGER, section_id INTEGER,
kodi_id INTEGER, kodi_id INTEGER,
fanart_synced INTEGER,
last_sync INTEGER) last_sync INTEGER)
''') ''')
plexdb.cursor.execute(''' plexdb.cursor.execute('''
@ -318,7 +254,6 @@ def initialize():
artist_id INTEGER, # plex_id of the parent artist artist_id INTEGER, # plex_id of the parent artist
parent_id INTEGER, # kodi_id of the parent artist parent_id INTEGER, # kodi_id of the parent artist
kodi_id INTEGER, kodi_id INTEGER,
fanart_synced INTEGER,
last_sync INTEGER) last_sync INTEGER)
''') ''')
plexdb.cursor.execute(''' plexdb.cursor.execute('''
@ -331,9 +266,7 @@ def initialize():
album_id INTEGER, # plex_id of the parent album album_id INTEGER, # plex_id of the parent album
parent_id INTEGER, # kodi_id of the parent album parent_id INTEGER, # kodi_id of the parent album
kodi_id INTEGER, kodi_id INTEGER,
kodi_fileid INTEGER,
kodi_pathid INTEGER, kodi_pathid INTEGER,
fanart_synced INTEGER,
last_sync INTEGER) last_sync INTEGER)
''') ''')
plexdb.cursor.execute(''' plexdb.cursor.execute('''

View file

@ -1,12 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .. import variables as v
class Movies(object): class Movies(object):
def add_movie(self, plex_id=None, checksum=None, section_id=None, def add_movie(self, plex_id, checksum, section_id, kodi_id, kodi_fileid,
kodi_id=None, kodi_fileid=None, kodi_pathid=None, kodi_pathid, last_sync):
last_sync=None):
""" """
Appends or replaces an entry into the plex table for movies Appends or replaces an entry into the plex table for movies
""" """
@ -22,7 +22,7 @@ class Movies(object):
last_sync) last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''' '''
self.plexcursor.execute( self.cursor.execute(
query, query,
(plex_id, (plex_id,
checksum, checksum,
@ -45,6 +45,25 @@ class Movies(object):
fanart_synced INTEGER, fanart_synced INTEGER,
last_sync INTEGER last_sync INTEGER
""" """
self.cursor.execute('SELECT * FROM movie WHERE plex_id = ?', if plex_id is None:
return
self.cursor.execute('SELECT * FROM movie WHERE plex_id = ? LIMIT 1',
(plex_id, )) (plex_id, ))
return self.cursor.fetchone() return self.entry_to_movie(self.cursor.fetchone())
@staticmethod
def entry_to_movie(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_MOVIE,
'kodi_type': v.KODI_TYPE_MOVIE,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'kodi_id': entry[3],
'kodi_fileid': entry[4],
'kodi_pathid': entry[5],
'fanart_synced': entry[6],
'last_sync': entry[7]
}

View file

@ -0,0 +1,240 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals
from .. import variables as v
class Music(object):
def add_artist(self, plex_id, checksum, section_id, kodi_id, last_sync):
"""
Appends or replaces music artist entry into the plex table
"""
query = '''
INSERT OR REPLACE INTO artist(
plex_id,
checksum,
section_id,
kodi_id,
last_sync)
VALUES (?, ?, ?, ?, ?)
'''
self.cursor.execute(
query,
(plex_id,
checksum,
section_id,
kodi_id,
last_sync))
def add_album(self, plex_id, checksum, section_id, artist_id, parent_id,
kodi_id, last_sync):
"""
Appends or replaces an entry into the plex table
"""
query = '''
INSERT OR REPLACE INTO album(
plex_id,
checksum,
section_id,
artist_id,
parent_id,
kodi_id,
last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?)
'''
self.cursor.execute(
query,
(plex_id,
checksum,
section_id,
artist_id,
parent_id,
kodi_id,
last_sync))
def add_song(self, plex_id, checksum, section_id, artist_id, grandparent_id,
album_id, parent_id, kodi_id, kodi_fileid, kodi_pathid,
last_sync):
"""
Appends or replaces an entry into the plex table
"""
query = '''
INSERT OR REPLACE INTO track(
plex_id,
checksum,
section_id,
artist_id,
grandparent_id,
album_id,
parent_id,
kodi_id,
kodi_fileid,
kodi_pathid,
last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
'''
self.cursor.execute(
query,
(plex_id,
checksum,
section_id,
artist_id,
grandparent_id,
album_id,
parent_id,
kodi_id,
kodi_fileid,
kodi_pathid,
last_sync))
def artist(self, plex_id):
"""
Returns the show info as a tuple for the TV show with plex_id:
plex_id INTEGER PRIMARY KEY,
checksum INTEGER UNIQUE,
section_id INTEGER,
kodi_id INTEGER,
last_sync INTEGER
"""
if plex_id is None:
return
self.cursor.execute('SELECT * FROM artist WHERE plex_id = ? LIMIT 1',
(plex_id, ))
return self.entry_to_artist(self.cursor.fetchone())
def album(self, plex_id):
"""
Returns the show info as a tuple for the TV show with plex_id:
plex_id INTEGER PRIMARY KEY,
checksum INTEGER UNIQUE,
section_id INTEGER,
artist_id INTEGER, # plex_id of the parent artist
parent_id INTEGER, # kodi_id of the parent artist
kodi_id INTEGER,
last_sync INTEGER
"""
if plex_id is None:
return
self.cursor.execute('SELECT * FROM album WHERE plex_id = ? LIMIT 1',
(plex_id, ))
return self.entry_to_album(self.cursor.fetchone())
def song(self, plex_id):
"""
Returns the show info as a tuple for the TV show with plex_id:
plex_id INTEGER PRIMARY KEY,
checksum INTEGER UNIQUE,
section_id INTEGER,
artist_id INTEGER, # plex_id of the parent artist
grandparent_id INTEGER, # kodi_id of the parent artist
album_id INTEGER, # plex_id of the parent album
parent_id INTEGER, # kodi_id of the parent album
kodi_id INTEGER,
kodi_pathid INTEGER,
last_sync INTEGER
"""
if plex_id is None:
return
self.cursor.execute('SELECT * FROM track WHERE plex_id = ? LIMIT 1',
(plex_id, ))
return self.entry_to_song(self.cursor.fetchone())
@staticmethod
def entry_to_song(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_SONG,
'kodi_type': v.KODI_TYPE_SONG,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'artist_id': entry[3],
'grandparent_id': entry[4],
'album_id': entry[5],
'parent_id': entry[6],
'kodi_id': entry[7],
'kodi_pathid': entry[8],
'last_sync': entry[9]
}
@staticmethod
def entry_to_album(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_ALBUM,
'kodi_type': v.KODI_TYPE_ALBUM,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'artist_id': entry[3],
'parent_id': entry[4],
'kodi_id': entry[5],
'last_sync': entry[6]
}
@staticmethod
def entry_to_artist(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_ARTIST,
'kodi_type': v.KODI_TYPE_ARTIST,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'kodi_id': entry[3],
'last_sync': entry[4]
}
def album_has_songs(self, plex_id):
"""
Returns True if there are songs left for the album with plex_id
"""
self.cursor.execute('SELECT plex_id FROM track WHERE album_id = ? LIMIT 1',
(plex_id, ))
return self.cursor.fetchone() is not None
def artist_has_albums(self, plex_id):
"""
Returns True if there are albums left for the artist with plex_id
"""
self.cursor.execute('SELECT plex_id FROM album WHERE artist_id = ? LIMIT 1',
(plex_id, ))
return self.cursor.fetchone() is not None
def artist_has_songs(self, plex_id):
"""
Returns True if there are episodes left for the show with plex_id
"""
self.cursor.execute('SELECT plex_id FROM track WHERE artist_id = ? LIMIT 1',
(plex_id, ))
return self.cursor.fetchone() is not None
def song_by_album(self, plex_id):
"""
Returns an iterator for all songs that have a parent album_id with
a value of plex_id
"""
self.cursor.execute('SELECT * FROM track WHERE album_id = ?',
(plex_id, ))
return (self.entry_to_song(x) for x in self.cursor)
def song_by_artist(self, plex_id):
"""
Returns an iterator for all songs that have a grandparent artist_id
with a value of plex_id
"""
self.cursor.execute('SELECT * FROM track WHERE artist_id = ?',
(plex_id, ))
return (self.entry_to_song(x) for x in self.cursor)
def album_by_artist(self, plex_id):
"""
Returns an iterator for all albums that have a parent artist_id
with a value of plex_id
"""
self.cursor.execute('SELECT * FROM album WHERE artist_id = ?',
(plex_id, ))
return (self.entry_to_album(x) for x in self.cursor)

View file

@ -1,80 +1,100 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .. import variables as v
class TVShows(object): class TVShows(object):
def add_show(self, plex_id=None, checksum=None, section_id=None, def add_show(self, plex_id, checksum, section_id, kodi_id, kodi_pathid,
kodi_id=None, kodi_pathid=None, last_sync=None): last_sync):
""" """
Appends or replaces tv show entry into the plex table Appends or replaces tv show entry into the plex table
""" """
query = ''' query = '''
INSERT OR REPLACE INTO show( INSERT OR REPLACE INTO show(
plex_id plex_id,
checksum checksum,
section_id section_id,
kodi_id kodi_id,
kodi_pathid kodi_pathid,
fanart_synced fanart_synced,
last_sync) last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
''' '''
self.plexcursor.execute( self.cursor.execute(
query, query,
(plex_id, checksum, section_id, kodi_id, kodi_pathid, 0, (plex_id,
checksum,
section_id,
kodi_id,
kodi_pathid,
0,
last_sync)) last_sync))
def add_season(self, plex_id=None, checksum=None, section_id=None, def add_season(self, plex_id, checksum, section_id, show_id, parent_id,
show_id=None, parent_id=None, kodi_id=None, last_sync=None): kodi_id, last_sync):
""" """
Appends or replaces an entry into the plex table Appends or replaces an entry into the plex table
""" """
query = ''' query = '''
INSERT OR REPLACE INTO season( INSERT OR REPLACE INTO season(
plex_id plex_id,
checksum checksum,
section_id section_id,
show_id show_id,
parent_id parent_id,
kodi_id kodi_id,
fanart_synced fanart_synced,
last_sync) last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''' '''
self.plexcursor.execute( self.cursor.execute(
query, query,
(plex_id, checksum, section_id, show_id, parent_id, (plex_id,
kodi_id, 0, last_sync)) checksum,
section_id,
show_id,
parent_id,
kodi_id,
0,
last_sync))
def add_episode(self, plex_id=None, checksum=None, section_id=None, def add_episode(self, plex_id, checksum, section_id, show_id,
show_id=None, grandparent_id=None, season_id=None, grandparent_id, season_id, parent_id, kodi_id, kodi_fileid,
parent_id=None, kodi_id=None, kodi_fileid=None, kodi_pathid, last_sync):
kodi_pathid=None, last_sync=None):
""" """
Appends or replaces an entry into the plex table Appends or replaces an entry into the plex table
""" """
query = ''' query = '''
INSERT OR REPLACE INTO episode( INSERT OR REPLACE INTO episode(
plex_id plex_id,
checksum 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,
fanart_synced fanart_synced,
last_sync) last_sync)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''' '''
self.plexcursor.execute( self.cursor.execute(
query, query,
(plex_id, checksum, section_id, show_id, grandparent_id, (plex_id,
season_id, parent_id, kodi_id, kodi_fileid, kodi_pathid, checksum,
0, last_sync)) section_id,
show_id,
grandparent_id,
season_id,
parent_id,
kodi_id,
kodi_fileid,
kodi_pathid,
0,
last_sync))
def show(self, plex_id): def show(self, plex_id):
""" """
@ -87,9 +107,11 @@ class TVShows(object):
fanart_synced INTEGER, fanart_synced INTEGER,
last_sync INTEGER last_sync INTEGER
""" """
if plex_id is None:
return
self.cursor.execute('SELECT * FROM show WHERE plex_id = ? LIMIT 1', self.cursor.execute('SELECT * FROM show WHERE plex_id = ? LIMIT 1',
(plex_id, )) (plex_id, ))
return self.cursor.fetchone() return self.entry_to_show(self.cursor.fetchone())
def season(self, plex_id): def season(self, plex_id):
""" """
@ -103,9 +125,11 @@ class TVShows(object):
fanart_synced INTEGER, fanart_synced INTEGER,
last_sync INTEGER last_sync INTEGER
""" """
if plex_id is None:
return
self.cursor.execute('SELECT * FROM season WHERE plex_id = ? LIMIT 1', self.cursor.execute('SELECT * FROM season WHERE plex_id = ? LIMIT 1',
(plex_id, )) (plex_id, ))
return self.cursor.fetchone() return self.entry_to_season(self.cursor.fetchone())
def episode(self, plex_id): def episode(self, plex_id):
""" """
@ -123,9 +147,65 @@ class TVShows(object):
fanart_synced INTEGER, fanart_synced INTEGER,
last_sync INTEGER last_sync INTEGER
""" """
if plex_id is None:
return
self.cursor.execute('SELECT * FROM episode WHERE plex_id = ? LIMIT 1', self.cursor.execute('SELECT * FROM episode WHERE plex_id = ? LIMIT 1',
(plex_id, )) (plex_id, ))
return self.cursor.fetchone() return self.entry_to_episode(self.cursor.fetchone())
@staticmethod
def entry_to_episode(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_EPISODE,
'kodi_type': v.KODI_TYPE_EPISODE,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'show_id': entry[3],
'grandparent_id': entry[4],
'season_id': entry[5],
'parent_id': entry[6],
'kodi_id': entry[7],
'kodi_fileid': entry[8],
'kodi_pathid': entry[9],
'fanart_synced': entry[10],
'last_sync': entry[11]
}
@staticmethod
def entry_to_show(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_SHOW,
'kodi_type': v.KODI_TYPE_SHOW,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'kodi_id': entry[3],
'kodi_pathid': entry[4],
'fanart_synced': entry[5],
'last_sync': entry[6]
}
@staticmethod
def entry_to_season(entry):
if not entry:
return
return {
'plex_type': v.PLEX_TYPE_SEASON,
'kodi_type': v.KODI_TYPE_SEASON,
'plex_id': entry[0],
'checksum': entry[1],
'section_id': entry[2],
'show_id': entry[3],
'parent_id': entry[4],
'kodi_id': entry[5],
'fanart_synced': entry[6],
'last_sync': entry[7]
}
def season_has_episodes(self, plex_id): def season_has_episodes(self, plex_id):
""" """