From 40ac4a0e8c8c03fd30f3c35c7b60fc1dd0c6b0e8 Mon Sep 17 00:00:00 2001
From: angelblue05 <angelblue.dev@gmail.com>
Date: Wed, 3 Oct 2018 18:25:51 -0500
Subject: [PATCH] Check db version

---
 .../resource.language.en_gb/strings.po        |   8 +
 resources/lib/database/emby_db.py             | 277 +-----------------
 resources/lib/database/queries.py             |   8 +
 resources/lib/entrypoint/service.py           |  25 ++
 service.py                                    |  23 +-
 5 files changed, 61 insertions(+), 280 deletions(-)

diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 89c4df79..9042899e 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -446,6 +446,14 @@ msgctxt "#33021"
 msgid "Gathering:"
 msgstr ""
 
+msgctxt "#33022"
+msgid "Detected the database needs to be recreated for this version of Emby for Kodi. Proceed?"
+msgstr ""
+
+msgctxt "#33023"
+msgid "Emby for Kodi will work correctly until the database is reset."
+msgstr ""
+
 msgctxt "#33025"
 msgid "Completed in:"
 msgstr ""
diff --git a/resources/lib/database/emby_db.py b/resources/lib/database/emby_db.py
index 60e34bc3..dc3cc744 100644
--- a/resources/lib/database/emby_db.py
+++ b/resources/lib/database/emby_db.py
@@ -148,283 +148,18 @@ class EmbyDatabase():
     def remove_media_by_parent_id(self, *args):
         self.cursor.execute(QU.delete_media_by_parent_id, args)
 
-
-
-
-
-    """
     def get_version(self, version=None):
 
         if version is not None:
-            self.embycursor.execute("DELETE FROM version")
-            query = "INSERT INTO version(idVersion) VALUES (?)"
-            self.embycursor.execute(query, (version,))
+
+            self.cursor.execute(QU.delete_version)
+            self.cursor.execute(QU.add_version, (version,))
         else:
-            query = "SELECT idVersion FROM version"
-            self.embycursor.execute(query)
             try:
-                version = self.embycursor.fetchone()[0]
-            except TypeError:
+                self.cursor.execute(QU.get_version)
+                version = self.cursor.fetchone()[0]
+            except Exception as error:
                 pass
 
         return version
-
-    def getViews(self):
-
-        views = []
-
-        query = ' '.join((
-
-            "SELECT view_id",
-            "FROM view"
-        ))
-        self.embycursor.execute(query)
-        rows = self.embycursor.fetchall()
-        for row in rows:
-            views.append(row[0])
-        
-        return views
-
-    def getView_embyId(self, item_id):
-        # Returns ancestors using embyId
-        url = "{server}/emby/Items/%s/Ancestors?UserId={UserId}&format=json" % item_id
-
-        try:
-            view_list = self.download(url)
-        except Exception as error:
-            log.info("Error getting views: " + str(error))
-            view_list = []
-
-        if view_list is None:
-            view_list = []
-
-        for view in view_list:
-
-            if view['Type'] == "CollectionFolder":
-                # Found view
-                view_id = view['Id']
-                break
-        else: # No view found
-            return [None, None]
-
-        # Compare to view table in emby database
-        query = ' '.join((
-
-            "SELECT view_name",
-            "FROM view",
-            "WHERE view_id = ?"
-        ))
-        self.embycursor.execute(query, (view_id,))
-        try:
-            view_name = self.embycursor.fetchone()[0]
-        except TypeError:
-            view_name = None
-
-        return [view_name, view_id]
-
-    def getView_byId(self, viewid):
-
-
-        query = ' '.join((
-
-            "SELECT view_name, media_type, kodi_tagid",
-            "FROM view",
-            "WHERE view_id = ?"
-        ))
-        self.embycursor.execute(query, (viewid,))
-        view = self.embycursor.fetchone()
-        
-        return view
-
-    def getView_byType(self, mediatype):
-
-        views = []
-
-        query = ' '.join((
-
-            "SELECT view_id, view_name",
-            "FROM view",
-            "WHERE media_type = ?"
-        ))
-        self.embycursor.execute(query, (mediatype,))
-        rows = self.embycursor.fetchall()
-        for row in rows:
-            views.append({
-
-                'id': row[0],
-                'name': row[1],
-                'mediatype': mediatype
-            })
-
-        if mediatype in ('tvshows', 'movies'):
-            query = ' '.join((
-                "SELECT view_id, view_name",
-                "FROM view",
-                "WHERE media_type = ?"
-            ))
-
-            self.embycursor.execute(query, ("mixed",))
-            rows = self.embycursor.fetchall()
-            for row in rows:
-                views.append({
-
-                    'id': row[0],
-                    'name': row[1],
-                    'mediatype': "mixed"
-                })
-
-        return views
-
-    def getView_byName(self, tagname):
-
-        query = ' '.join((
-
-            "SELECT view_id",
-            "FROM view",
-            "WHERE view_name = ?"
-        ))
-        self.embycursor.execute(query, (tagname,))
-        try:
-            view = self.embycursor.fetchone()[0]
-        
-        except TypeError:
-            view = None
-
-        return view
-
-    def addView(self, embyid, name, mediatype, tagid, group_series):
-
-        query = (
-            '''
-            INSERT INTO view(
-                view_id, view_name, media_type, kodi_tagid, group_series)
-
-            VALUES (?, ?, ?, ?, ?)
-            '''
-        )
-        self.embycursor.execute(query, (embyid, name, mediatype, tagid, group_series))
-
-    def get_view_grouped_series(self, view_id):
-
-        query = ' '.join((
-
-            "SELECT group_series",
-            "FROM view",
-            "WHERE view_id = ?"
-        ))
-        try:
-            self.embycursor.execute(query, (view_id,))
-            return self.embycursor.fetchone()
-        except: return False
-
-    def update_view_grouped_series(self, view_id, group_series):
-
-        query = ' '.join((
-
-            "UPDATE view",
-            "SET group_series = ?",
-            "WHERE view_id = ?"
-        ))
-        self.embycursor.execute(query, (group_series, view_id))
-
-    def updateView(self, name, tagid, mediafolderid):
-
-        query = ' '.join((
-
-            "UPDATE view",
-            "SET view_name = ?, kodi_tagid = ?",
-            "WHERE view_id = ?"
-        ))
-        self.embycursor.execute(query, (name, tagid, mediafolderid))
-
-    def removeView(self, viewid):
-
-        query = ' '.join((
-
-            "DELETE FROM view",
-            "WHERE view_id = ?"
-        ))
-        self.embycursor.execute(query, (viewid,))
-
-    def getItem_byId(self, embyid):
-
-        query = ' '.join((
-
-            "SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, emby_type",
-            "FROM emby",
-            "WHERE emby_id = ?"
-        ))
-        try:
-            self.embycursor.execute(query, (embyid,))
-            item = self.embycursor.fetchone()
-            return item
-        except: return None
-
-    def getItem_byView(self, mediafolderid):
-
-        query = ' '.join((
-
-            "SELECT kodi_id",
-            "FROM emby",
-            "WHERE media_folder = ?"
-        ))
-        self.embycursor.execute(query, (mediafolderid,))
-        return self.embycursor.fetchall()
-
-    def get_item_by_view(self, view_id):
-
-        query = ' '.join((
-
-            "SELECT emby_id",
-            "FROM emby",
-            "WHERE media_folder = ?"
-        ))
-        self.embycursor.execute(query, (view_id,))
-        return self.embycursor.fetchall()
-
-
-    def get_checksum_by_view(self, media_type, view_id):
-
-        query = ' '.join((
-
-            "SELECT emby_id, checksum",
-            "FROM emby",
-            "WHERE emby_type = ?",
-            "AND media_folder = ?"
-        ))
-        self.embycursor.execute(query, (media_type, view_id,))
-        return self.embycursor.fetchall()
-
-    def getMediaType_byId(self, embyid):
-
-        query = ' '.join((
-
-            "SELECT emby_type",
-            "FROM emby",
-            "WHERE emby_id = ?"
-        ))
-        self.embycursor.execute(query, (embyid,))
-        try:
-            itemtype = self.embycursor.fetchone()[0]
-        
-        except TypeError:
-            itemtype = None
-
-        return itemtype
-
-    def sortby_mediaType(self, itemids, unsorted=True):
-
-        sorted_items = {}
-        
-        for itemid in itemids:
-            
-            mediatype = self.getMediaType_byId(itemid)
-            if mediatype:
-                sorted_items.setdefault(mediatype, []).append(itemid)
-            elif unsorted:
-                sorted_items.setdefault('Unsorted', []).append(itemid)
-
-        return sorted_items
-
-    """
         
\ No newline at end of file
diff --git a/resources/lib/database/queries.py b/resources/lib/database/queries.py
index 529be85e..e03a8f0f 100644
--- a/resources/lib/database/queries.py
+++ b/resources/lib/database/queries.py
@@ -80,6 +80,9 @@ get_items_by_media =    """ SELECT  emby_id
                             FROM    emby 
                             WHERE   media_type = ?
                         """
+get_version =           """ SELECT  idVersion 
+                            FROM    version
+                        """
 
 
 
@@ -116,6 +119,9 @@ add_reference_song_obj =    [   "{Id}","{SongId}",None,"{PathId}","Audio","song"
 add_view =              """ INSERT OR REPLACE INTO  view(view_id, view_name, media_type)
                             VALUES                  (?, ?, ?)
                         """
+add_version =           """ INSERT OR REPLACE INTO  version(idVersion) 
+                            VALUES                  (?)
+                        """
 
 
 update_reference =      """	UPDATE 	emby 
@@ -172,3 +178,5 @@ delete_parent_boxset_obj = [    None, "{Movie}"
 delete_media_by_parent_id = """ DELETE FROM emby 
                                 WHERE       emby_parent_id = ? 
                             """
+delete_version =        """ DELETE FROM version
+                        """
diff --git a/resources/lib/entrypoint/service.py b/resources/lib/entrypoint/service.py
index 219fb945..8a66d8e9 100644
--- a/resources/lib/entrypoint/service.py
+++ b/resources/lib/entrypoint/service.py
@@ -22,6 +22,7 @@ from views import Views, verify_kodi_defaults
 from helper import _, window, settings, event, dialog, find, compare_version
 from downloader import get_objects
 from emby import Emby
+from database import Database, emby_db, reset
 
 #################################################################################################
 
@@ -68,6 +69,8 @@ class Service(xbmc.Monitor):
         LOG.warn("Using dynamic paths: %s", settings('useDirectPaths') == "0")
         LOG.warn("Log Level: %s", self.settings['log_level'])
 
+        self.check_version()
+
         verify_kodi_defaults()
         Views().get_nodes()
         window('emby.connected.bool', True)
@@ -132,6 +135,28 @@ class Service(xbmc.Monitor):
             self.library_thread.stop_client()
             self.library_thread = None
 
+    def check_version(self):
+
+        ''' Check the database version to ensure we do not need to do a reset.
+        '''
+        with Database('emby') as embydb:
+
+            version = emby_db.EmbyDatabase(embydb.cursor).get_version()
+            LOG.info("---[ db/%s ]", version)
+
+        if version and compare_version(version, "3.1.0") < 0:
+            resp = dialog("yesno", heading=_('addon_name'), line1=_(33022))
+
+            if not resp:
+
+                LOG.warn("Database version is out of date! USER IGNORED!")
+                dialog("ok", heading=_('addon_name'), line1=_(33023))
+
+                raise Exception("User backed out of a required database reset")
+            else:
+                reset()
+
+                raise Exception("Completed database reset")
 
     def check_update(self):
 
diff --git a/service.py b/service.py
index a22e0579..07a90a44 100644
--- a/service.py
+++ b/service.py
@@ -38,19 +38,24 @@ DELAY = int(settings('startupDelay') or 0)
 
 if __name__ == "__main__":
 
-    LOG.warn("--->[ service ]")
+    LOG.warn("-->[ service ]")
     LOG.warn("Delay startup by %s seconds.", DELAY)
 
-    session = Service()
-
     try:
-        if DELAY and xbmc.Monitor().waitForAbort(DELAY):
-            raise Exception("Aborted during startup delay")
+        session = Service()
+
+        try:
+            if DELAY and xbmc.Monitor().waitForAbort(DELAY):
+                raise Exception("Aborted during startup delay")
+
+            session.service()
+        except Exception as error: # TODO, build exceptions
+            LOG.exception(error)
+            session.shutdown()
 
-        session.service()
     except Exception as error:
-
+        ''' Issue initializing the service.
+        '''
         LOG.exception(error)
-        session.shutdown()
 
-    LOG.warn("---<[ service ]")
+    LOG.warn("--<[ service ]")