jellyfin-kodi/resources/lib/database.py
2018-03-07 16:53:24 -06:00

239 lines
7.7 KiB
Python

# -*- coding: utf-8 -*-
#################################################################################################
import logging
import sqlite3
import sys
import traceback
import xbmc
import xbmcgui
import xbmcplugin
import xbmcvfs
from views import Playlist, VideoNodes
from utils import window, should_stop, settings, language
#################################################################################################
log = logging.getLogger("EMBY."+__name__)
KODI = xbmc.getInfoLabel('System.BuildVersion')[:2]
#################################################################################################
def video_database():
db_version = {
'17': 107,# Krypton
'18': 109 # Leia
}
return xbmc.translatePath("special://database/MyVideos%s.db"
% db_version.get(KODI, "")).decode('utf-8')
def music_database():
db_version = {
'17': 60, # Krypton
'18': 70 # Leia
}
return xbmc.translatePath("special://database/MyMusic%s.db"
% db_version.get(KODI, "")).decode('utf-8')
def texture_database():
return xbmc.translatePath("special://database/Textures13.db").decode('utf-8')
def emby_database():
return xbmc.translatePath("special://database/emby.db").decode('utf-8')
def kodi_commit():
# verification for the Kodi video scan
kodi_scan = window('emby_kodiScan') == "true"
count = 0
while kodi_scan:
log.info("kodi scan is running, waiting...")
if count == 10:
log.info("flag still active, but will try to commit")
window('emby_kodiScan', clear=True)
elif should_stop() or xbmc.Monitor().waitForAbort(1):
log.info("commit unsuccessful. sync terminating")
return False
kodi_scan = window('emby_kodiScan') == "true"
count += 1
return True
class DatabaseConn(object):
# To be called as context manager - i.e. with DatabaseConn() as conn: #dostuff
def __init__(self, database_file="video", commit_on_close=True, timeout=120):
"""
database_file can be custom: emby, texture, music, video, :memory: or path to the file
commit_mode set to None to autocommit (isolation_level). See python documentation.
"""
self.db_file = database_file
self.commit_on_close = commit_on_close
self.timeout = timeout
def __enter__(self):
# Open the connection
self.path = self._SQL(self.db_file)
#traceback.print_stack()
if settings('dblock') == "true":
self.conn = sqlite3.connect(self.path, isolation_level=None, timeout=self.timeout)
else:
self.conn = sqlite3.connect(self.path, timeout=self.timeout)
log.info("opened: %s - %s", self.path, id(self.conn))
self.cursor = self.conn.cursor()
if self.db_file == "emby":
verify_emby_database(self.cursor)
self.conn.commit()
return self.cursor
def _SQL(self, media_type):
databases = {
'emby': emby_database,
'texture': texture_database,
'music': music_database,
'video': video_database
}
return databases[media_type]() if media_type in databases else self.db_file
def __exit__(self, exc_type, exc_val, exc_tb):
# Close the connection
changes = self.conn.total_changes
if exc_type is not None:
# Errors were raised in the with statement
log.error("Type: %s Value: %s", exc_type, exc_val)
if self.commit_on_close == True and changes:
log.info("number of rows updated: %s", changes)
if self.db_file == "video":
kodi_commit()
self.conn.commit()
log.info("commit: %s", self.path)
log.info("closing: %s - %s", self.path, id(self.conn))
self.cursor.close()
self.conn.close()
def verify_emby_database(cursor):
# Create the tables for the emby database
# emby, view, version
log.info("Verifying emby DB")
cursor.execute(
"""CREATE TABLE IF NOT EXISTS emby(
emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT,
kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER,
checksum INTEGER)""")
cursor.execute(
"""CREATE TABLE IF NOT EXISTS view(
view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER, group_series TEXT)""")
cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)")
columns = cursor.execute("SELECT * FROM view")
if 'group_series' not in [description[0] for description in columns.description]:
log.info("Add missing column group_series")
cursor.execute("ALTER TABLE view ADD COLUMN group_series 'TEXT'")
def db_reset():
dialog = xbmcgui.Dialog()
if not dialog.yesno(language(29999), language(33074)):
return
# first stop any db sync
window('emby_online', value="reset")
window('emby_shouldStop', value="true")
count = 10
while window('emby_dbScan') == "true":
log.info("Sync is running, will retry: %s..." % count)
count -= 1
if count == 0:
dialog.ok(language(29999), language(33085))
return
xbmc.sleep(1000)
# Clean up the playlists
Playlist().delete_playlists()
# Clean up the video nodes
VideoNodes().deleteNodes()
# Wipe the kodi databases
log.warn("Resetting the Kodi video database.")
with DatabaseConn('video') as cursor:
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
for row in rows:
tablename = row[0]
if tablename != "version":
cursor.execute("DELETE FROM " + tablename)
if settings('enableMusic') == "true":
log.warn("Resetting the Kodi music database.")
with DatabaseConn('music') as cursor:
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
for row in rows:
tablename = row[0]
if tablename != "version":
cursor.execute("DELETE FROM " + tablename)
# Wipe the emby database
log.warn("Resetting the Emby database.")
with DatabaseConn('emby') as cursor:
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
for row in rows:
tablename = row[0]
if tablename != "version":
cursor.execute("DELETE FROM " + tablename)
cursor.execute('DROP table IF EXISTS emby')
cursor.execute('DROP table IF EXISTS view')
cursor.execute("DROP table IF EXISTS version")
# Offer to wipe cached thumbnails
if dialog.yesno(language(29999), language(33086)):
log.warn("Resetting all cached artwork")
# Remove all existing textures first
import artwork
artwork.Artwork().delete_cache()
# reset the install run flag
settings('SyncInstallRunDone', value="false")
# Remove emby info
resp = dialog.yesno(language(29999), language(33087))
if resp:
import connectmanager
# Delete the settings
addondir = xbmc.translatePath(
"special://profile/addon_data/plugin.video.emby/").decode('utf-8')
dataPath = "%ssettings.xml" % addondir
xbmcvfs.delete(dataPath)
connectmanager.ConnectManager().clear_data()
dialog.ok(heading=language(29999), line1=language(33088))
xbmc.executebuiltin('RestartApp')
try:
xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())
except:
pass