2018-11-09 07:22:16 +11:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import absolute_import, division, unicode_literals
|
|
|
|
from logging import getLogger
|
|
|
|
|
|
|
|
from .video import KodiVideoDB
|
|
|
|
from .music import KodiMusicDB
|
|
|
|
from .texture import KodiTextureDB
|
|
|
|
|
2018-11-19 00:59:17 +11:00
|
|
|
from .. import path_ops, utils, timing, variables as v
|
2018-11-09 07:22:16 +11:00
|
|
|
|
|
|
|
LOG = getLogger('PLEX.kodi_db')
|
|
|
|
|
|
|
|
|
|
|
|
def kodiid_from_filename(path, kodi_type=None, db_type=None):
|
|
|
|
"""
|
|
|
|
Returns kodi_id if we have an item in the Kodi video or audio database with
|
|
|
|
said path. Feed with either koditype, e.v. 'movie', 'song' or the DB
|
|
|
|
you want to poll ('video' or 'music')
|
|
|
|
Returns None, <kodi_type> if not possible
|
|
|
|
"""
|
|
|
|
kodi_id = None
|
|
|
|
path = utils.try_decode(path)
|
|
|
|
try:
|
|
|
|
filename = path.rsplit('/', 1)[1]
|
|
|
|
path = path.rsplit('/', 1)[0] + '/'
|
|
|
|
except IndexError:
|
|
|
|
filename = path.rsplit('\\', 1)[1]
|
|
|
|
path = path.rsplit('\\', 1)[0] + '\\'
|
|
|
|
if kodi_type == v.KODI_TYPE_SONG or db_type == 'music':
|
|
|
|
with KodiMusicDB() as kodidb:
|
|
|
|
try:
|
2018-11-13 19:02:34 +11:00
|
|
|
kodi_id = kodidb.song_id_from_filename(filename, path)
|
2018-11-09 07:22:16 +11:00
|
|
|
except TypeError:
|
|
|
|
LOG.debug('No Kodi audio db element found for path %s', path)
|
|
|
|
else:
|
|
|
|
kodi_type = v.KODI_TYPE_SONG
|
|
|
|
else:
|
|
|
|
with KodiVideoDB() as kodidb:
|
|
|
|
try:
|
|
|
|
kodi_id, kodi_type = kodidb.video_id_from_filename(filename,
|
|
|
|
path)
|
|
|
|
except TypeError:
|
2018-11-23 18:54:09 +11:00
|
|
|
LOG.debug('No kodi video db element found for path %s file %s',
|
|
|
|
path, filename)
|
2018-11-09 07:22:16 +11:00
|
|
|
return kodi_id, kodi_type
|
|
|
|
|
|
|
|
|
|
|
|
def setup_kodi_default_entries():
|
|
|
|
"""
|
|
|
|
Makes sure that we retain the Kodi standard databases. E.g. that there
|
|
|
|
is a dummy artist with ID 1
|
|
|
|
"""
|
|
|
|
if utils.settings('enableMusic') == 'true':
|
|
|
|
with KodiMusicDB() as kodidb:
|
|
|
|
kodidb.cursor.execute('''
|
|
|
|
INSERT OR REPLACE INTO artist(
|
|
|
|
idArtist,
|
|
|
|
strArtist,
|
|
|
|
strMusicBrainzArtistID)
|
|
|
|
VALUES (?, ?, ?)
|
|
|
|
''', (1, '[Missing Tag]', 'Artist Tag Missing'))
|
2018-12-03 03:10:53 +11:00
|
|
|
kodidb.cursor.execute('''
|
|
|
|
INSERT OR REPLACE INTO role(
|
|
|
|
idRole,
|
|
|
|
strRole)
|
|
|
|
VALUES (?, ?)
|
|
|
|
''', (1, 'Artist'))
|
2018-11-09 07:22:16 +11:00
|
|
|
if v.KODIVERSION >= 18:
|
2018-12-03 01:25:54 +11:00
|
|
|
kodidb.cursor.execute('DELETE FROM versiontagscan')
|
2018-11-09 07:22:16 +11:00
|
|
|
kodidb.cursor.execute('''
|
2018-12-03 01:25:54 +11:00
|
|
|
INSERT INTO versiontagscan(
|
2018-11-09 07:22:16 +11:00
|
|
|
idVersion,
|
|
|
|
iNeedsScan,
|
|
|
|
lastscanned)
|
|
|
|
VALUES (?, ?, ?)
|
|
|
|
''', (v.DB_MUSIC_VERSION[v.KODIVERSION],
|
|
|
|
0,
|
2018-11-19 00:59:17 +11:00
|
|
|
timing.kodi_now()))
|
2018-11-09 07:22:16 +11:00
|
|
|
|
|
|
|
|
|
|
|
def reset_cached_images():
|
|
|
|
LOG.info('Resetting cached artwork')
|
|
|
|
# Remove all existing textures first
|
|
|
|
path = path_ops.translate_path('special://thumbnails/')
|
|
|
|
if path_ops.exists(path):
|
|
|
|
path_ops.rmtree(path, ignore_errors=True)
|
|
|
|
paths = ('', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
|
|
'a', 'b', 'c', 'd', 'e', 'f',
|
|
|
|
'Video', 'plex')
|
|
|
|
for path in paths:
|
|
|
|
new_path = path_ops.translate_path('special://thumbnails/%s' % path)
|
2018-12-03 03:46:35 +11:00
|
|
|
try:
|
|
|
|
path_ops.makedirs(path_ops.encode_path(new_path))
|
|
|
|
except OSError:
|
|
|
|
pass
|
2018-11-09 07:22:16 +11:00
|
|
|
with KodiTextureDB() as kodidb:
|
|
|
|
for row in kodidb.cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type=?',
|
|
|
|
('table', )):
|
|
|
|
if row[0] != 'version':
|
|
|
|
kodidb.cursor.execute("DELETE FROM %s" % row[0])
|
|
|
|
|
|
|
|
|
|
|
|
def wipe_dbs(music=True):
|
|
|
|
"""
|
|
|
|
Completely resets the Kodi databases 'video', 'texture' and 'music' (if
|
|
|
|
music sync is enabled)
|
|
|
|
"""
|
|
|
|
LOG.warn('Wiping Kodi databases!')
|
|
|
|
kinds = [KodiVideoDB, KodiTextureDB]
|
|
|
|
if music:
|
|
|
|
kinds.append(KodiMusicDB)
|
|
|
|
for db in kinds:
|
|
|
|
with db() as kodidb:
|
|
|
|
kodidb.cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
|
|
|
|
tables = kodidb.cursor.fetchall()
|
|
|
|
tables = [i[0] for i in tables]
|
|
|
|
if 'version' in tables:
|
|
|
|
tables.remove('version')
|
|
|
|
if 'versiontagscan' in tables:
|
|
|
|
tables.remove('versiontagscan')
|
|
|
|
for table in tables:
|
|
|
|
kodidb.cursor.execute('DELETE FROM %s' % table)
|
|
|
|
setup_kodi_default_entries()
|
2018-11-13 19:28:19 +11:00
|
|
|
# Delete SQLITE wal files
|
2018-11-09 07:22:16 +11:00
|
|
|
import xbmc
|
2018-11-13 19:28:19 +11:00
|
|
|
db_dir = xbmc.translatePath('special://database').decode('utf-8')
|
|
|
|
for root, _, files in path_ops.walk(db_dir):
|
|
|
|
for file in files:
|
|
|
|
if path_ops.path.splitext(file)[1].lower() in ('.db-shm', '.db-wal'):
|
|
|
|
try:
|
|
|
|
path_ops.remove(path_ops.path.join(root, file))
|
|
|
|
except OSError:
|
|
|
|
LOG.info('Could not delete temp DB file %s', file)
|
|
|
|
# Make sure Kodi knows we wiped the databases
|
2018-11-09 07:22:16 +11:00
|
|
|
xbmc.executebuiltin('UpdateLibrary(video)')
|
|
|
|
if utils.settings('enableMusic') == 'true':
|
|
|
|
xbmc.executebuiltin('UpdateLibrary(music)')
|
|
|
|
|
|
|
|
|
|
|
|
KODIDB_FROM_PLEXTYPE = {
|
|
|
|
v.PLEX_TYPE_MOVIE: KodiVideoDB,
|
|
|
|
v.PLEX_TYPE_SHOW: KodiVideoDB,
|
|
|
|
v.PLEX_TYPE_SEASON: KodiVideoDB,
|
|
|
|
v.PLEX_TYPE_EPISODE: KodiVideoDB,
|
|
|
|
v.PLEX_TYPE_ARTIST: KodiMusicDB,
|
|
|
|
v.PLEX_TYPE_ALBUM: KodiMusicDB,
|
|
|
|
v.PLEX_TYPE_SONG: KodiMusicDB
|
|
|
|
}
|