From 8a990ba217bf055b943fecd0a3ee14a243c66ba2 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Fri, 1 May 2015 13:30:21 +0200 Subject: [PATCH] first work on the transition to use kodi db for all actions --- resources/lib/LibrarySync.py | 690 ++++++-------------------- resources/lib/ReadEmbyDB.py | 51 +- resources/lib/ReadKodiDB.py | 122 ++--- resources/lib/Utils.py | 2 +- resources/lib/WriteKodiDB.py | 905 +++++++++++------------------------ service.py | 4 +- 6 files changed, 464 insertions(+), 1310 deletions(-) diff --git a/resources/lib/LibrarySync.py b/resources/lib/LibrarySync.py index b6135af4..d95d2989 100644 --- a/resources/lib/LibrarySync.py +++ b/resources/lib/LibrarySync.py @@ -12,6 +12,7 @@ import inspect import threading import urllib from datetime import datetime, timedelta, time +from itertools import chain import urllib2 import os @@ -47,23 +48,21 @@ class LibrarySync(): completed = True connection = utils.KodiSQL() cursor = connection.cursor() + + #TEMP --> add new columns + try: + cursor.execute("alter table movie ADD COLUMN 'embyId' TEXT") + cursor.execute("alter table tvshow ADD COLUMN 'embyId' TEXT") + cursor.execute("alter table episode ADD COLUMN 'embyId' TEXT") + cursor.execute("alter table musicvideo ADD COLUMN 'embyId' TEXT") + connection.commit() + except: pass + # sync movies - if(syncInstallRunDone == False): # on first install run do a full sync with model progress dialog - completed = completed and self.TvShowsSync(connection, cursor,True, True) - completed = completed and self.MoviesSync(connection, cursor,True, True) - completed = completed and self.MusicVideosSync(True, True,connection , cursor) - elif(startupDone == False): # on first run after startup do a inc then a full sync - self.TvShowsSync(connection, cursor,False, False) - self.MoviesSync(connection, cursor,False, False) - self.MusicVideosSync(False, False, connection,cursor) - self.TvShowsSync(connection, cursor,True, False) - self.MoviesSync(connection, cursor,True, False) - self.MusicVideosSync(True, False,connection,cursor) - else: # on scheduled sync do a full sync - self.TvShowsSync(connection, cursor,True, False) - self.MoviesSync(connection, cursor,True, False) - self.MusicVideosSync(True, False,connection,cursor) - + self.MoviesSync(connection,cursor,True) + #sync Tvshows and episodes + self.TvShowsSync(connection,cursor,True) + # set the install done setting if(syncInstallRunDone == False and completed): addon = xbmcaddon.Addon(id='plugin.video.emby') #force a new instance of the addon @@ -78,540 +77,145 @@ class LibrarySync(): cursor.close() return True - - def MoviesSync(self,connection, cursor, fullsync, installFirstRun,itemList = []): + + def MoviesSync(self,connection,cursor,installFirstRun,itemList = []): + + pDialog = xbmcgui.DialogProgressBG() + pDialog.create('Sync DB', 'Sync Movies') + + views = ReadEmbyDB().getCollections("movies") + + allKodiMovieIds = list() + allEmbyMovieIds = list() + + for view in views: + + allMB3Movies = ReadEmbyDB().getMovies(view.get('id')) + allKodiMovies = ReadKodiDB().getKodiMovies(connection, cursor) + #### PROCESS ADDS AND UPDATES ### + for item in allMB3Movies: + + if not item.get('IsFolder'): + allEmbyMovieIds.append(item["Id"]) + + kodiMovie = None + for kodimovie in allKodiMovies: + allKodiMovieIds.append(kodimovie[1]) + if kodimovie[1] == item["Id"]: + kodiMovie = kodimovie + + if kodiMovie == None: + allKodiMovieIds.append(item["Id"]) + WriteKodiDB().addOrUpdateMovieToKodiLibrary(item["Id"],connection, cursor, view.get('title')) + else: + # TODO --> compare with eTag + if kodiMovie[2] != item["Name"] or item["Id"] in itemList: + WriteKodiDB().addOrUpdateMovieToKodiLibrary(item["Id"],connection, cursor, view.get('title')) + + #### PROCESS DELETES ##### + allEmbyMovieIds = set(allEmbyMovieIds) + for kodiId in allKodiMovieIds: + if not kodiId in allEmbyMovieIds: + WINDOW.setProperty(kodiId,"deleted") + WriteKodiDB().deleteMovieFromKodiLibrary(kodiId, connection, cursor) + + if(pDialog != None): + pDialog.close() + + def TvShowsSync(self,connection,cursor,installFirstRun,itemList = []): + + pDialog = xbmcgui.DialogProgressBG() + pDialog.create('Sync DB', 'Sync TV Shows') + + views = ReadEmbyDB().getCollections("tvshows") + + allKodiTvShowIds = list() + allEmbyTvShowIds = list() + + for view in views: + + allEmbyTvShows = ReadEmbyDB().getTvShows(view.get('id')) + allKodiTvShows = ReadKodiDB().getKodiTvShows(connection, cursor) + + #### TVSHOW: PROCESS ADDS AND UPDATES ### + for item in allEmbyTvShows: + + if item.get('IsFolder') and item.get('RecursiveItemCount') != 0: + allEmbyTvShowIds.append(item["Id"]) + + #build a list with all Id's and get the existing entry (if exists) in Kodi DB + kodiShow = None + for kodishow in allKodiTvShows: + allKodiTvShowIds.append(kodishow[1]) + if kodishow[1] == item["Id"]: + kodiShow = kodishow + + if kodiShow == None: + # Tv show doesn't exist in Kodi yet so proceed and add it + allKodiTvShowIds.append(item["Id"]) + kodiId = WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"],connection, cursor, view.get('title')) + else: + kodiId = kodishow[0] + # If there are changes to the item, perform a full sync of the item + if kodiShow[2] != item["Name"] or item["Id"] in itemList: + WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"],connection, cursor, view.get('title')) + + #### PROCESS EPISODES ###### + self.EpisodesSync(connection,cursor,installFirstRun, item["Id"], kodiId, itemList) + + #### TVSHOW: PROCESS DELETES ##### + allEmbyTvShowIds = set(allEmbyTvShowIds) + for kodiId in allKodiTvShowIds: + if not kodiId in allEmbyTvShowIds: + WINDOW.setProperty(kodiId,"deleted") + WriteKodiDB().deleteTvShowFromKodiLibrary(kodiId, connection, cursor) + + if(pDialog != None): + pDialog.close() + + + def EpisodesSync(self,connection,cursor,installFirstRun, embyShowId, kodiShowId, itemList = []): + WINDOW = xbmcgui.Window( 10000 ) - pDialog = None - startedSync = datetime.today() - try: - addon = xbmcaddon.Addon(id='plugin.video.emby') - dbSyncIndication = addon.getSetting("dbSyncIndication") - - if(installFirstRun or dbSyncIndication == "Dialog Progress"): - pDialog = xbmcgui.DialogProgress() - elif(dbSyncIndication == "BG Progress"): - pDialog = xbmcgui.DialogProgressBG() - - if(pDialog != None): - pDialog.create('Sync DB', 'Sync DB') - - totalItemsAdded = 0 - totalItemsUpdated = 0 - totalItemsDeleted = 0 - - allEmbyMovieIds = list() - - views = ReadEmbyDB().getCollections("movies") - viewCount = len(views) - viewCurrent = 1 - progressTitle = "" - - for view in views: - - #process new movies - allMB3Movies = ReadEmbyDB().getMovies(id = view.get('id'), fullinfo=True, fullSync = fullsync, itemList = itemList) - allKodiIds = set(ReadKodiDB().getKodiMoviesIds(True)) - - if(self.ShouldStop(pDialog)): - return False - - if(allMB3Movies == None): - return False - - if(pDialog != None): - progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount) - pDialog.update(0, progressTitle) - total = len(allMB3Movies) + 1 - count = 1 - - for item in allMB3Movies: - - if not item.get('IsFolder'): - allEmbyMovieIds.append(item["Id"]) - item['Tag'] = [] - item['Tag'].append(view.get('title')) - - if item["Id"] not in allKodiIds: - WriteKodiDB().addMovieToKodiLibrary(item,connection, cursor) - totalItemsAdded += 1 - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Adding Movie: " + str(count)) - count += 1 - - if(self.ShouldStop(pDialog)): - return False - - if(pDialog != None): - progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount) - pDialog.update(0, progressTitle, "") - total = len(allMB3Movies) + 1 - count = 1 - - #process updates - allKodiMovies = ReadKodiDB().getKodiMovies(True) - for item in allMB3Movies: - - if not item.get('IsFolder'): - item['Tag'] = [] - item['Tag'].append(view.get('title')) - - if allKodiMovies != None: - kodimovie = allKodiMovies.get(item["Id"], None) - else: - kodimovie = None - - userData = API().getUserData(item) - - if(kodimovie != None): - updated = WriteKodiDB().updateMovieToKodiLibrary_Batched(item, kodimovie, connection, cursor) - if(updated): - totalItemsUpdated += 1 - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Updating Movie: " + str(count)) - count += 1 - - viewCurrent += 1 - - # process box sets - TODO cope with movies removed from a set - if fullsync: - - if(pDialog != None): - progressTitle = "Sync DB : BoxSets" - pDialog.update(0, progressTitle, "Retrieving Boxset List") - - utils.logMsg("Sync Movies", "BoxSet Sync Started", 1) - boxsets = ReadEmbyDB().getBoxSets() - - if(pDialog != None): - total = len(boxsets) + 1 - count = 1 - - for boxset in boxsets: - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Updating BoxSet: " + str(count) + " of " + str(total)) - count += 1 - if(self.ShouldStop(pDialog)): - return False - boxsetMovies = ReadEmbyDB().getMoviesInBoxSet(boxset["Id"]) - WriteKodiDB().addBoxsetToKodiLibrary(boxset,connection, cursor) - - for boxsetMovie in boxsetMovies: - if(self.ShouldStop(pDialog)): - return False - WriteKodiDB().updateBoxsetToKodiLibrary(boxsetMovie,boxset) - - utils.logMsg("Sync Movies", "BoxSet Sync Finished", 1) - - if(pDialog != None): - progressTitle = "Removing Deleted Items" - pDialog.update(0, progressTitle, "") - - if(self.ShouldStop(pDialog)): - return False - - # process any deletes only at fullsync - if fullsync: - allKodiIds = ReadKodiDB().getKodiMoviesIds(True) - allEmbyMovieIds = set(allEmbyMovieIds) - for kodiId in allKodiIds: - if not kodiId in allEmbyMovieIds: - WINDOW.setProperty(kodiId,"deleted") - WriteKodiDB().deleteMovieFromKodiLibrary(kodiId) - totalItemsDeleted += 1 - - if(self.ShouldStop(pDialog)): - return False - - # display notification if set up - notificationString = "" - if(totalItemsAdded > 0): - notificationString += "Added:" + str(totalItemsAdded) + " " - if(totalItemsUpdated > 0): - notificationString += "Updated:" + str(totalItemsUpdated) + " " - if(totalItemsDeleted > 0): - notificationString += "Deleted:" + str(totalItemsDeleted) + " " - - timeTaken = datetime.today() - startedSync - timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60) - utils.logMsg("Sync Movies", "Finished " + timeTakenString + " " + notificationString, 0) - - if(dbSyncIndication == "Notify OnChange" and notificationString != ""): - notificationString = "(" + timeTakenString + ") " + notificationString - xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)") - elif(dbSyncIndication == "Notify OnFinish"): - if(notificationString == ""): - notificationString = "Done" - notificationString = "(" + timeTakenString + ") " + notificationString - xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)") - - finally: - if(pDialog != None): - pDialog.close() + allKodiEpisodeIds = list() + allEmbyEpisodeIds = list() - return True + allEmbyEpisodes = ReadEmbyDB().getEpisodes(embyShowId) + allKodiEpisodes = ReadKodiDB().getKodiEpisodes(connection, cursor, kodiShowId) + + #### EPISODES: PROCESS ADDS AND UPDATES ### + for item in allEmbyEpisodes: + + allEmbyEpisodeIds.append(item["Id"]) + + #build a list with all Id's and get the existing entry (if exists) in Kodi DB + kodiEpisode = None + for kodiepisode in allKodiEpisodes: + allKodiEpisodeIds.append(kodiepisode[1]) + if kodiepisode[1] == item["Id"]: + kodiEpisode = kodiepisode + + if kodiEpisode == None: + # Episode doesn't exist in Kodi yet so proceed and add it + allKodiEpisodeIds.append(item["Id"]) + WriteKodiDB().addOrUpdateEpisodeToKodiLibrary(item["Id"], kodiShowId, connection, cursor) + else: + # If there are changes to the item, perform a full sync of the item + if kodiEpisode[2] != item["Name"] or item["Id"] in itemList: + WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"], kodiShowId, connection, cursor) - def TvShowsSync(self, connection, cursor ,fullsync, installFirstRun, itemList = []): + #### EPISODES: PROCESS DELETES ##### + allEmbyEpisodeIds = set(allEmbyEpisodeIds) + print allEmbyEpisodeIds + for kodiId in allKodiEpisodeIds: + if not kodiId in allEmbyEpisodeIds: + WINDOW.setProperty(kodiId,"deleted") + print "deleting ???-->" + kodiId + #WriteKodiDB().deleteEpisodeFromKodiLibrary(kodiId, connection, cursor) - addon = xbmcaddon.Addon(id='plugin.video.emby') - WINDOW = xbmcgui.Window( 10000 ) - pDialog = None - startedSync = datetime.today() - - try: - dbSyncIndication = addon.getSetting("dbSyncIndication") - - if(installFirstRun or dbSyncIndication == "Dialog Progress"): - pDialog = xbmcgui.DialogProgress() - elif(dbSyncIndication == "BG Progress"): - pDialog = xbmcgui.DialogProgressBG() - - if(pDialog != None): - pDialog.create('Sync DB', 'Sync DB') - - totalItemsAdded = 0 - totalItemsUpdated = 0 - totalItemsDeleted = 0 - allTVShows = list() - allMB3EpisodeIds = list() #for use with deletions - allKodiEpisodeIds = [] # for use with deletions - - views = ReadEmbyDB().getCollections("tvshows") - viewCount = len(views) - viewCurrent = 1 - progressTitle = "" - for view in views: - - progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount) - - # incremental sync --> new episodes only - if fullsync == False: - - latestMBEpisodes = ReadEmbyDB().getLatestEpisodes(fullinfo = True, itemList = itemList) - utils.logMsg("Sync TV", "Inc Sync Started on : " + str(len(latestMBEpisodes)) + " : " + str(itemList), 1) - - if latestMBEpisodes != None: - allKodiTvShowsIds = set(ReadKodiDB().getKodiTvShowsIds(True)) - - # get included TV Shows - showList = [] - for episode in latestMBEpisodes: - if(episode["SeriesId"] not in showList): - showList.append(episode["SeriesId"]) - - utils.logMsg("Incremental TV Sync", "Included TV Show List : " + str(showList), 0) - - if(pDialog != None): - pDialog.update(0, progressTitle) - total = len(showList) + 1 - count = 1 - - # process included TV Shows - for showID in showList: - - embyTvShow = ReadEmbyDB().getFullItem(showID) - - if(showID not in allKodiTvShowsIds): - utils.logMsg("Incremental TV Sync", "Adding TV Show : " + embyTvShow.get("Name"), 1) - WriteKodiDB().addTVShowToKodiLibrary(embyTvShow, connection, cursor) - - kodiTvShow = ReadKodiDB().getKodiTVShow(showID) - utils.logMsg("Incremental TV Sync", "Updating TV Show : " + embyTvShow.get("Name"), 1) - WriteKodiDB().updateTVShowToKodiLibrary(embyTvShow, kodiTvShow, connection, cursor) - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Processing TV Shows : " + str(count)) - count += 1 - - if(pDialog != None): - pDialog.update(0, progressTitle) - total = len(latestMBEpisodes) + 1 - count = 1 - - # process new episodes - for episode in latestMBEpisodes: - if(self.ShouldStop(pDialog)): - return False - - WriteKodiDB().addEpisodeToKodiLibrary(episode, connection, cursor) - progressAction = "Adding" - totalItemsAdded += 1 - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count)) - count += 1 - - #process updates - if(pDialog != None): - progressTitle = "Sync DB : Processing Episodes" - pDialog.update(0, progressTitle) - total = len(latestMBEpisodes) + 1 - count = 1 - - for episode in latestMBEpisodes: - if(self.ShouldStop(pDialog)): - return False - allKodiTVShows = ReadKodiDB().getKodiTvShows(False) - kodishow = allKodiTVShows.get(episode["SeriesId"],None) - kodiEpisodes = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],True,True) - - if(self.ShouldStop(pDialog)): - return False - - userData = API().getUserData(episode) - - if kodiEpisodes != None: - KodiItem = kodiEpisodes.get(episode.get("Id"), None) - if(KodiItem != None): - WriteKodiDB().updateEpisodeToKodiLibrary(episode, KodiItem, connection, cursor) - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Updating Episode: " + str(count)) - count += 1 - - - # full sync --> Tv shows and Episodes - if fullsync: - viewTVShows = list() - tvShowData = ReadEmbyDB().getTVShows(id = view.get('id') , fullinfo = True, fullSync = True) - allKodiIds = set(ReadKodiDB().getKodiTvShowsIds(True)) - - if(self.ShouldStop(pDialog)): - return False - - if (tvShowData == None): - return False - - if(pDialog != None): - progressTitle = "Sync DB : Processing TV Shows" - pDialog.update(0, progressTitle) - total = len(tvShowData) + 1 - count = 1 - - # add TV Shows - for item in tvShowData: - if item.get('IsFolder') and item.get('RecursiveItemCount') != 0: - allTVShows.append(item["Id"]) - viewTVShows.append(item["Id"]) - item['Tag'] = [] - item['Tag'].append(view.get('title')) - progMessage = "Processing" - if item["Id"] not in allKodiIds: - WriteKodiDB().addTVShowToKodiLibrary(item,connection, cursor) - totalItemsAdded += 1 - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Adding Tv Show: " + str(count)) - count += 1 - - if(pDialog != None): - progressTitle = "Sync DB : Processing TV Shows" - pDialog.update(0, progressTitle, "") - total = len(viewTVShows) + 1 - count = 1 - - # update TV Shows - allKodiTVShows = ReadKodiDB().getKodiTvShows(True) - for item in tvShowData: - if item.get('IsFolder'): - item['Tag'] = [] - item['Tag'].append(view.get('title')) - if allKodiTVShows != None: - kodishow = allKodiTVShows.get(item["Id"],None) - else: - kodishow = None - - if(kodishow != None): - updated = WriteKodiDB().updateTVShowToKodiLibrary(item,kodishow,connection, cursor) - if(updated): - totalItemsUpdated += 1 - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Updating Tv Show: " + str(count)) - count += 1 - - - # do episode adds - allEpisodes = list() - showTotal = len(viewTVShows) - showCurrent = 1 - for tvshow in viewTVShows: - - episodeData = ReadEmbyDB().getEpisodes(tvshow,True) - if episodeData != None: - - if(self.ShouldStop(pDialog)): - return False - - if(pDialog != None): - progressTitle = "Sync DB : Processing Tv Show " + str(showCurrent) + " of " + str(showTotal) - pDialog.update(0, progressTitle) - total = len(episodeData) + 1 - count = 0 - - for item in episodeData: - - if(self.ShouldStop(pDialog)): - return False - - progressAction = "Adding" - WriteKodiDB().addEpisodeToKodiLibrary(item, connection, cursor) - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count)) - count += 1 - - showCurrent += 1 - - # do episode updates - showCurrent = 1 - for tvshow in viewTVShows: - episodeData = ReadEmbyDB().getEpisodes(tvshow,True) - - kodiEpisodes = None - allKodiTVShows = ReadKodiDB().getKodiTvShows(False) - if allKodiTVShows != None: - kodishow = allKodiTVShows.get(tvshow,None) - if kodishow != None: - kodiEpisodes = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],True,True) - - if(self.ShouldStop(pDialog)): - return False - - if(pDialog != None): - progressTitle = "Sync DB : Processing Tv Show " + str(showCurrent) + " of " + str(showTotal) - pDialog.update(0, progressTitle) - total = len(episodeData) + 1 - count = 0 - - #we have to compare the lists somehow - for item in episodeData: - #add episodeId to the list of all episodes for use later on the deletes - allMB3EpisodeIds.append(item["Id"]) - - matchFound = False - - userData = API().getUserData(item) - - if kodiEpisodes != None: - KodiItem = kodiEpisodes.get(item.get("Id"), None) - if(KodiItem != None): - updated = WriteKodiDB().updateEpisodeToKodiLibrary(item, KodiItem, connection, cursor) - if(updated): - totalItemsUpdated += 1 - - if(self.ShouldStop(pDialog)): - return False - - # update progress bar - if(pDialog != None): - percentage = int(((float(count) / float(total)) * 100)) - pDialog.update(percentage, progressTitle, "Updating Episode: " + str(count)) - count += 1 - - - #add all kodi episodes to a list with episodes for use later on to delete episodes - #the mediabrowser ID is set as uniqueID in the NFO... for some reason this has key 'unknown' in the json response - if kodishow != None: - show = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],False,False) - if show != None: - for episode in show: - dict = {'episodeid': str(episode["uniqueid"]["unknown"]),'tvshowid': tvshow} - allKodiEpisodeIds.append(dict) - - showCurrent += 1 - - if(pDialog != None): - progressTitle = "Removing Deleted Items" - pDialog.update(0, progressTitle) - - if(self.ShouldStop(pDialog)): - return False - - # DELETES -- EPISODES - # process any deletes only at fullsync - allMB3EpisodeIdsSet = set(allMB3EpisodeIds) - for episode in allKodiEpisodeIds: - if episode.get('episodeid') not in allMB3EpisodeIdsSet: - WINDOW.setProperty("embyid" + str(episode.get('episodeid')),"deleted") - WriteKodiDB().deleteEpisodeFromKodiLibrary(episode.get('episodeid'),episode.get('tvshowid')) - totalItemsDeleted += 1 - - # DELETES -- TV SHOWS - if fullsync: - allKodiShows = ReadKodiDB().getKodiTvShowsIds(True) - allMB3TVShows = set(allTVShows) - for show in allKodiShows: - if not show in allMB3TVShows: - WriteKodiDB().deleteTVShowFromKodiLibrary(show) - totalItemsDeleted += 1 - - if(self.ShouldStop(pDialog)): - return False - - # display notification if set up - notificationString = "" - if(totalItemsAdded > 0): - notificationString += "Added:" + str(totalItemsAdded) + " " - if(totalItemsUpdated > 0): - notificationString += "Updated:" + str(totalItemsUpdated) + " " - if(totalItemsDeleted > 0): - notificationString += "Deleted:" + str(totalItemsDeleted) + " " - - timeTaken = datetime.today() - startedSync - timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60) - utils.logMsg("Sync Episodes", "Finished " + timeTakenString + " " + notificationString, 0) - - if(dbSyncIndication == "Notify OnChange" and notificationString != ""): - notificationString = "(" + timeTakenString + ") " + notificationString - xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)") - elif(dbSyncIndication == "Notify OnFinish"): - if(notificationString == ""): - notificationString = "Done" - notificationString = "(" + timeTakenString + ") " + notificationString - xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)") - - finally: - if(pDialog != None): - pDialog.close() - - return True def MusicVideosSync(self, fullsync, installFirstRun,connection, cursor): diff --git a/resources/lib/ReadEmbyDB.py b/resources/lib/ReadEmbyDB.py index 4d80455c..23773820 100644 --- a/resources/lib/ReadEmbyDB.py +++ b/resources/lib/ReadEmbyDB.py @@ -6,30 +6,22 @@ import xbmc import xbmcgui import xbmcaddon + + from DownloadUtils import DownloadUtils addon = xbmcaddon.Addon(id='plugin.video.emby') class ReadEmbyDB(): - def getMovies(self, id, fullinfo = False, fullSync = True, itemList = []): + def getMovies(self, id): result = None doUtils = DownloadUtils() - - if fullSync: - sortstring = "&SortBy=SortName" - else: - if(len(itemList) > 0): # if we want a certain list specify it - #sortstring = "&Ids=" + ",".join(itemList) - sortstring = "" # work around for now until ParetnId and Id work together - else: # just get the last 20 created items - sortstring = "&Limit=20&SortBy=DateCreated" - - if fullinfo: - url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring) - else: - url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring) + + #only get basic info for our sync-compares + sortstring = "&SortBy=SortName" + url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring) jsonData = doUtils.downloadUrl(url) if (jsonData == ""): @@ -37,14 +29,6 @@ class ReadEmbyDB(): if (jsonData[u'Items'] != ""): result = jsonData[u'Items'] - - # work around for now until ParetnId and Id work together - if (result != None and len(result) > 0 and len(itemList) > 0): - newResult = [] - for item in result: - if (item[u'Id'] in itemList): - newResult.append(item) - result = newResult return result @@ -98,20 +82,14 @@ class ReadEmbyDB(): return result - def getTVShows(self, id, fullinfo = False, fullSync = False): + def getTvShows(self, id): result = None doUtils = DownloadUtils() - - if not fullSync: - sortstring = "&Limit=20&SortBy=DateCreated" - else: - sortstring = "&SortBy=SortName" - if fullinfo: - url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring) - else: - url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring) + #only get basic info for our sync-compares + sortstring = "&SortBy=SortName" + url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring) jsonData = doUtils.downloadUrl(url) if (jsonData == ""): @@ -138,15 +116,12 @@ class ReadEmbyDB(): return result - def getEpisodes(self, showId, fullinfo = False): + def getEpisodes(self, showId): result = None doUtils = DownloadUtils() - if fullinfo: - url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId - else: - url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId + url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId jsonData = doUtils.downloadUrl(url) if (jsonData == ""): diff --git a/resources/lib/ReadKodiDB.py b/resources/lib/ReadKodiDB.py index f5acdb26..14b0872a 100644 --- a/resources/lib/ReadKodiDB.py +++ b/resources/lib/ReadKodiDB.py @@ -30,71 +30,38 @@ class ReadKodiDB(): movies = result['movies'] movie = movies[0] for item in movies: - if item["imdbnumber"] == id: + if id in item["file"]: movie = item break return movie def getEmbyIdByKodiId(self, kodiid, type): - #returns the emby id by search on kodi id - xbmc.sleep(sleepVal) - embyId = None - json_response = None + connection = utils.KodiSQL() + cursor = connection.cursor() if type == "movie": - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieDetails", "params": { "movieid": %d, "properties" : ["imdbnumber","file"] }, "id": "libMovies"}' %kodiid) + cursor.execute("SELECT embyId as embyId FROM movie WHERE idMovie = ?",(kodiid,)) if type == "episode": - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": %d, "properties": ["file","uniqueid"]}, "id": 1}' %kodiid) + cursor.execute("SELECT embyId as embyId FROM episode WHERE idEpisode = ?",(kodiid,)) if type == "musicvideo": - connection = utils.KodiSQL() - cursor = connection.cursor() - cursor.execute("SELECT c23 as MBid FROM musicvideo WHERE idMVideo = ?",(kodiid,)) - result = cursor.fetchone() - cursor.close() - if result != None: - embyId = result[0] + cursor.execute("SELECT embyId as embyId FROM musicvideo WHERE idMVideo = ?",(kodiid,)) + if type == "tvshow": + cursor.execute("SELECT embyId as embyId FROM tvshow WHERE idShow = ?",(kodiid,)) - if json_response != None: - jsonobject = json.loads(json_response.decode('utf-8','replace')) - if(jsonobject.has_key('result')): - result = jsonobject['result'] - resulttype = type + "details" - if(result.has_key(resulttype)): - item = result[resulttype] - if type == "movie": - if item.has_key('imdbnumber'): - embyId = item['imdbnumber'] - if type == "episode": - if item.has_key('uniqueid'): - if item['uniqueid'].has_key('unknown'): - embyId = item["uniqueid"]["unknown"] + result = cursor.fetchone() + cursor.close() + if result != None: + embyId = result[0] return embyId - def getKodiMovies(self,fullInfo = False): + def getKodiMovies(self, connection, cursor): #returns all movies in Kodi db - xbmc.sleep(sleepVal) - if fullInfo: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["art", "rating", "thumbnail", "fanart", "resume", "runtime", "year", "genre", "cast", "trailer", "country", "lastplayed", "studio", "set", "imdbnumber", "mpaa", "tagline", "plotoutline","plot", "sorttitle", "director", "writer", "playcount", "tag", "file"] }, "id": "libMovies"}') - else: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["resume", "playcount", "imdbnumber", "lastplayed", "file"] }, "id": "libMovies"}') - jsonobject = json.loads(json_response.decode('utf-8','replace')) - movies = None - - if(jsonobject.has_key('result')): - result = jsonobject['result'] - if(result.has_key('movies')): - movies = result['movies'] - - kodiMovieMap = None - if(movies != None and len(movies) > 0): - kodiMovieMap = {} - for kodimovie in movies: - key = kodimovie["imdbnumber"] #extract the id from the imdbnumber - kodiMovieMap[key] = kodimovie - - return kodiMovieMap + cursor.execute("SELECT idMovie, embyId, c00 FROM movie") + allmovies = cursor.fetchall() + #this will return a list with tuples of all items returned from the database + return allmovies def getKodiMoviesIds(self,returnMB3Ids = False): # returns a list of movieIds or MB3 Id's from all movies currently in the Kodi library @@ -132,29 +99,11 @@ class ReadKodiDB(): return allKodiTvShowsIds - def getKodiTvShows(self,fullInfo = False): - #returns all tvshows in Kodi db inserted by MB - xbmc.sleep(sleepVal) - if fullInfo: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["art", "genre", "plot", "mpaa", "cast", "studio", "sorttitle", "title", "originaltitle", "imdbnumber", "year", "premiered", "rating", "thumbnail", "playcount", "lastplayed", "file", "fanart", "tag"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libTvShows"}') - else: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["sorttitle", "title", "playcount", "lastplayed", "imdbnumber", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libTvShows"}') - jsonobject = json.loads(json_response.decode('utf-8','replace')) - tvshows = None - - if(jsonobject.has_key('result')): - result = jsonobject['result'] - if(result.has_key('tvshows')): - tvshows = result['tvshows'] - - kodiShowMap = None - if(tvshows != None and len(tvshows) > 0): - kodiShowMap = {} - for kodishow in tvshows: - key = kodishow["imdbnumber"] #extract the id from the imdb number - kodiShowMap[key] = kodishow - - return kodiShowMap + def getKodiTvShows(self, connection, cursor): + cursor.execute("SELECT idShow, embyId, c00 FROM tvshow") + allshows = cursor.fetchall() + #this will return a list with tuples of all items returned from the database + return allshows def getKodiTVShow(self, id): xbmc.sleep(sleepVal) @@ -171,28 +120,11 @@ class ReadKodiDB(): break return tvshow - def getKodiEpisodes(self, KodiTvShowId, fullInfo = True, returnmap = True): - xbmc.sleep(sleepVal) - episodes = None - if fullInfo: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": %d, "properties": ["title", "playcount", "plot", "season", "episode", "showtitle", "file", "lastplayed", "rating", "resume", "art", "streamdetails", "firstaired", "runtime", "writer", "cast", "director", "dateadded", "uniqueid", "thumbnail", "fanart"], "sort": {"method": "episode"}}, "id": 1}' %KodiTvShowId) - else: - json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": %d, "properties": ["title", "playcount", "season", "episode", "lastplayed", "resume","file","uniqueid"], "sort": {"method": "episode"}}, "id": 1}' %KodiTvShowId) - jsonobject = json.loads(json_response.decode('utf-8','replace')) - episodes = None - if(jsonobject.has_key('result')): - result = jsonobject['result'] - if(result.has_key('episodes')): - episodes = result['episodes'] - if returnmap: - episodeMap = None - if(episodes != None): - episodeMap = {} - for KodiItem in episodes: - episodeMap[KodiItem["uniqueid"]["unknown"]] = KodiItem - return episodeMap - else: - return episodes + def getKodiEpisodes(self, connection, cursor, showid): + cursor.execute("SELECT idEpisode, embyId, c00 FROM episode WHERE idShow = ?", (showid,)) + allepisodes = cursor.fetchall() + #this will return a list with tuples of all items returned from the database + return allepisodes def getKodiEpisodeByMbItem(self, episodeid, tvshowid): episode = None diff --git a/resources/lib/Utils.py b/resources/lib/Utils.py index 4f47b77f..a9da6b5c 100644 --- a/resources/lib/Utils.py +++ b/resources/lib/Utils.py @@ -53,7 +53,7 @@ def convertEncoding(data): def KodiSQL(): connection = sqlite3.connect(getKodiDBPath()) - + return connection def getKodiDBPath(): diff --git a/resources/lib/WriteKodiDB.py b/resources/lib/WriteKodiDB.py index b46ccb44..d2cf5421 100644 --- a/resources/lib/WriteKodiDB.py +++ b/resources/lib/WriteKodiDB.py @@ -43,107 +43,7 @@ class WriteKodiDB(): else: downloadUtils.downloadUrl(watchedurl, type="DELETE") - def updateMovieToKodiLibrary_Batched(self, MBitem, KodiItem,connection, cursor): - addon = xbmcaddon.Addon(id='plugin.video.emby') - WINDOW = xbmcgui.Window(10000) - username = WINDOW.getProperty('currUser') - server = WINDOW.getProperty('server%s' % username) - - downloadUtils = DownloadUtils() - - timeInfo = API().getTimeInfo(MBitem) - userData=API().getUserData(MBitem) - people = API().getPeople(MBitem) - genre = API().getGenre(MBitem) - studios = API().getStudios(MBitem) - mediaStreams=API().getMediaStreams(MBitem) - - thumbPath = API().getArtwork(MBitem, "Primary") - - params = list() - - self.getArtworkParam_Batched(KodiItem, MBitem, params) - - #set Filename - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie", MBitem["Id"], connection, cursor) - - #update common properties - if KodiItem["runtime"] == 0: - self.getPropertyParam_Batched(KodiItem, "runtime", (int(timeInfo.get('Duration'))*60), params) - self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params) - self.getPropertyParam_Batched(KodiItem, "mpaa", MBitem.get("OfficialRating"), params) - self.getPropertyParam_Batched(KodiItem, "lastplayed", userData.get("LastPlayedDate"), params) - self.getPropertyParamArray_Batched(KodiItem, "tag", MBitem.get("Tag"), params) - - if MBitem.get("CommunityRating") != None: - self.getPropertyParam_Batched(KodiItem, "rating", Decimal(format(MBitem.get("CommunityRating"),'.1f')), params) - - self.getPropertyParam_Batched(KodiItem, "plot", MBitem.get("Overview"), params) - self.getPropertyParam_Batched(KodiItem, "plotoutline", MBitem.get("ShortOverview"), params) - self.getPropertyParam_Batched(KodiItem, "set", MBitem.get("TmdbCollectionName"), params) - self.getPropertyParam_Batched(KodiItem, "sorttitle", MBitem.get("SortName"), params) - - if MBitem.get("ProviderIds") != None: - if MBitem.get("ProviderIds").get("Imdb") != None: - self.getPropertyParam_Batched(KodiItem, "imdbnumber", MBitem.get("ProviderIds").get("Imdb"), params) - - # FIXME --> Taglines not returned by MB3 server !? - if MBitem.get("TagLines") != None: - self.getPropertyParam_Batched(KodiItem, "tagline", MBitem.get("TagLines")[0], params) - - self.getPropertyParamArray_Batched(KodiItem, "writer", people.get("Writer"), params) - self.getPropertyParamArray_Batched(KodiItem, "director", people.get("Director"), params) - self.getPropertyParamArray_Batched(KodiItem, "genre", MBitem.get("Genres"), params) - - if(studios != None): - for x in range(0, len(studios)): - studios[x] = studios[x].replace("/", "&") - self.getPropertyParamArray_Batched(KodiItem, "studio", studios, params) - - # FIXME --> ProductionLocations not returned by MB3 server !? - self.getPropertyParamArray_Batched(KodiItem, "country", MBitem.get("ProductionLocations"), params) - - #trailer link - trailerUrl = None - if MBitem.get("LocalTrailerCount") != None and MBitem.get("LocalTrailerCount") > 0: - itemTrailerUrl = "{server}/mediabrowser/Users/{UserId}/Items/%s/LocalTrailers?format=json" % MBitem.get("Id") - jsonData = downloadUtils.downloadUrl(itemTrailerUrl) - if (jsonData != ""): - trailerItem = jsonData - if trailerItem[0][u'LocationType'] == "FileSystem": - trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0][u'Id'], trailerItem[0]) - trailerUrl = utils.convertEncoding(trailerUrl) - self.getPropertyParam_Batched(KodiItem, "trailer", trailerUrl, params) - - - changes = False - # if there were movies changes then send the update via JSONRPC - if(len(params) > 0): - changes |= True - utils.logMsg("UpdateMovieParams", str(params), level = 2) - jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, %s}, "id": 1 }' - paramString = "" - paramLen = len(params) - for x in range(0, paramLen): - param = params[x] - paramString += param - if(x < paramLen-1): - paramString += ", " - jsoncommand = jsoncommand %(KodiItem['movieid'], paramString) - utils.logMsg("executeJSONRPC : ", jsoncommand, level = 2) - xbmc.sleep(sleepVal) - result = xbmc.executeJSONRPC(jsoncommand.encode("utf-8")) - - #add actors - changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"), "movie", connection, cursor) - - if(changes): - utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0) - - return changes - def updateMusicVideoToKodiLibrary_Batched(self, MBitem, KodiItem): addon = xbmcaddon.Addon(id='plugin.video.emby') port = addon.getSetting('port') @@ -201,74 +101,6 @@ class WriteKodiDB(): if(changes): utils.logMsg("Updated musicvideo to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0) - def updateTVShowToKodiLibrary( self, MBitem, KodiItem,connection, cursor ): - - addon = xbmcaddon.Addon(id='plugin.video.emby') - port = addon.getSetting('port') - host = addon.getSetting('ipaddress') - server = host + ":" + port - downloadUtils = DownloadUtils() - - timeInfo = API().getTimeInfo(MBitem) - userData=API().getUserData(MBitem) - people = API().getPeople(MBitem) - genre = API().getGenre(MBitem) - studios = API().getStudios(MBitem) - mediaStreams=API().getMediaStreams(MBitem) - - thumbPath = API().getArtwork(MBitem, "Primary") - - changes = False - - #set Filename - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - #make sure that the path always ends with a slash - playurl = playurl + "/" - self.setKodiFilename(KodiItem["tvshowid"], KodiItem["file"], playurl, "tvshow", MBitem["Id"], connection, cursor) - - #update/check all artwork - changes |= self.updateArtWork(KodiItem,MBitem) - - #update common properties - if MBitem.get("PremiereDate") != None: - premieredatelist = (MBitem.get("PremiereDate")).split("T") - premieredate = premieredatelist[0] - changes |= self.updateProperty(KodiItem,"premiered",premieredate,"tvshow") - - changes |= self.updatePropertyArray(KodiItem,"tag",MBitem.get("Tag"),"tvshow") - changes |= self.updateProperty(KodiItem,"mpaa",MBitem.get("OfficialRating"),"tvshow") - changes |= self.updateProperty(KodiItem,"lastplayed",MBitem.get("LastPlayedDate"),"tvshow") - - if MBitem.get("CommunityRating") != None: - changes |= self.updateProperty(KodiItem,"rating",Decimal(format(MBitem.get("CommunityRating"),'.1f')),"tvshow") - - changes |= self.updateProperty(KodiItem,"sorttitle",utils.convertEncoding(MBitem["SortName"]),"tvshow") - changes |= self.updateProperty(KodiItem,"title",utils.convertEncoding(MBitem["Name"]),"tvshow") - changes |= self.updateProperty(KodiItem,"plot",utils.convertEncoding(API().getOverview(MBitem)),"tvshow") - - # we use this to store the Emby ID so make sure we use that - changes |= self.updateProperty(KodiItem, "imdbnumber", MBitem.get("Id"), "tvshow") - - changes |= self.updatePropertyArray(KodiItem,"genre",MBitem.get("Genres"),"tvshow") - - if(studios != None): - for x in range(0, len(studios)): - studios[x] = studios[x].replace("/", "&") - changes |= self.updatePropertyArray(KodiItem,"studio",studios,"tvshow") - - # FIXME --> ProductionLocations not returned by MB3 server !? - changes |= self.updatePropertyArray(KodiItem, "country", MBitem.get("ProductionLocations"), "tvshow") - - #add actors - changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"tvshow", connection, cursor) - - #update season details - self.updateSeasons(MBitem, KodiItem,connection, cursor) - - if changes: - utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"]) - - return changes def updateEpisodeToKodiLibrary( self, MBitem, KodiItem, connection, cursor ): addon = xbmcaddon.Addon(id='plugin.video.emby') @@ -288,48 +120,7 @@ class WriteKodiDB(): #update/check all artwork changes |= self.updateArtWork(KodiItem,MBitem) - #set Filename (will update the filename in db if changed) - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - changes |= self.setKodiFilename(KodiItem["episodeid"], KodiItem["file"], playurl, "episode", MBitem["Id"], connection, cursor) - - #update common properties - if KodiItem["runtime"] == 0: - changes |= self.updateProperty(KodiItem,"runtime",(int(timeInfo.get('Duration'))*60),"episode") - changes |= self.updateProperty(KodiItem,"lastplayed",userData.get("LastPlayedDate"),"episode") - - if MBitem.get("PremiereDate") != None: - premieredatelist = (MBitem.get("PremiereDate")).split("T") - premieredate = premieredatelist[0] - premieretime = premieredatelist[1].split(".")[0] - firstaired = premieredate + " " + premieretime - # for Helix we use the whole time string, for kodi 15 we have to change to only the datestring - # see: http://forum.kodi.tv/showthread.php?tid=218743 - if KodiItem["firstaired"] != premieredate: - changes |= self.updateProperty(KodiItem,"firstaired",firstaired,"episode") - - if MBitem.get("CommunityRating") != None: - changes |= self.updateProperty(KodiItem,"rating",Decimal(format(MBitem.get("CommunityRating"),'.1f')),"episode") - - if MBitem.get("ParentIndexNumber") != None: - season = int(MBitem.get("ParentIndexNumber")) - changes |= self.updateProperty(KodiItem,"season",season,"episode") - # removed for now as setting c15 and c16 to -1 just shows specials in the special folder only - #if(season == 0): - # changes |= self.setSpecialAirsDetails(MBitem, KodiItem, connection, cursor) - - if MBitem.get("IndexNumber") != None: - episode = int(MBitem.get("IndexNumber")) - changes |= self.updateProperty(KodiItem,"episode",episode,"episode") - - #plot = utils.convertEncoding(API().getOverview(MBitem)) - plot = MBitem.get("Overview") - if(plot != None): - changes |= self.updateProperty(KodiItem,"plot",plot,"episode") - - title = utils.convertEncoding(MBitem["Name"]) - changes |= self.updateProperty(KodiItem,"title",title,"episode") - changes |= self.updatePropertyArray(KodiItem,"writer",people.get("Writer"),"episode") - changes |= self.updatePropertyArray(KodiItem,"director",people.get("Director"),"episode") + addOrUpdateEpisodeToKodiLibrary(MBitem, connection, cursor) #add actors changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"episode", connection, cursor) @@ -597,23 +388,50 @@ class WriteKodiDB(): return pendingChanges - def addMovieToKodiLibrary( self, MBitem ,connection, cursor): - #adds a movie to Kodi by directly inserting it to the DB while there is no addmovie available on the json API - #TODO: PR at Kodi team for a addMovie endpoint on their API + def addOrUpdateMovieToKodiLibrary( self, embyId ,connection, cursor, viewTag): addon = xbmcaddon.Addon(id='plugin.video.emby') WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) - downloadUtils = DownloadUtils() + MBitem = ReadEmbyDB().getFullItem(embyId) + + # If the item already exist in the local Kodi DB we'll perform a full item update + # If the item doesn't exist, we'll add it to the database + + cursor.execute("SELECT idMovie FROM movie WHERE embyId = ?",(MBitem["Id"],)) + result = cursor.fetchone() + if result != None: + movieid = result[0] + else: + movieid = None + timeInfo = API().getTimeInfo(MBitem) userData=API().getUserData(MBitem) - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - playurl = utils.convertEncoding(playurl) + #### The movie details ######### + runtime = int(timeInfo.get('Duration'))*60 + plot = utils.convertEncoding(API().getOverview(MBitem)) + title = utils.convertEncoding(MBitem["Name"]) + sorttitle = utils.convertEncoding(MBitem["SortName"]) + year = MBitem.get("ProductionYear") + rating = MBitem.get("CommunityRating") + + if MBitem.get("ShortOverview") != None: + shortplot = utils.convertEncoding(MBitem.get("ShortOverview")) + else: + shortplot = None + + trailerUrl = None + if MBitem.get("LocalTrailerCount") != None and MBitem.get("LocalTrailerCount") > 0: + itemTrailerUrl = "%s/mediabrowser/Users/%s/Items/%s/LocalTrailers?format=json" % (server, userid, MBitem.get("Id")) + jsonData = downloadUtils.downloadUrl(itemTrailerUrl) + if(jsonData != ""): + trailerItem = jsonData + trailerUrl = "plugin://plugin.video.emby/mode=play?id=" + trailerItem[0][u'Id'] if MBitem.get("DateCreated") != None: dateadded = MBitem["DateCreated"].replace("T"," ") @@ -621,14 +439,11 @@ class WriteKodiDB(): else: dateadded = None - # we need to store both the path and the filename seperately in the kodi db so we split them up - if "\\" in playurl: - filename = playurl.rsplit("\\",1)[-1] - path = playurl.replace(filename,"") - elif "/" in playurl: - filename = playurl.rsplit("/",1)[-1] - path = playurl.replace(filename,"") - + #### ADD OR UPDATE THE FILE AND PATH ########### + #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY + path = "plugin://plugin.video.emby/movies/" + filename = "plugin://plugin.video.emby/movies/?id=" MBitem["Id"] + "&mode=play" + #create the path cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) result = cursor.fetchone() @@ -656,44 +471,29 @@ class WriteKodiDB(): fileid = fileid + 1 pathsql="insert into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)" cursor.execute(pathsql, (fileid,pathid,filename,playcount,userData.get("LastPlayedDate"),dateadded)) - - runtime = int(timeInfo.get('Duration'))*60 - plot = utils.convertEncoding(API().getOverview(MBitem)) - title = utils.convertEncoding(MBitem["Name"]) - sorttitle = utils.convertEncoding(MBitem["SortName"]) - year = MBitem.get("ProductionYear") - rating = MBitem.get("CommunityRating") - if MBitem.get("ShortOverview") != None: - shortplot = utils.convertEncoding(MBitem.get("ShortOverview")) + + ##### ADD THE MOVIE ############ + if movieid == None: + #create the movie + cursor.execute("select coalesce(max(idMovie),0) as movieid from movie") + movieid = cursor.fetchone()[0] + movieid = movieid + 1 + pathsql="insert into movie(idMovie, idFile, c00, c01, c02, c05, c07, c10, c11, c16, c19, embyId) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + cursor.execute(pathsql, (movieid, fileid, title, plot, shortplot, rating, year, sorttitle, runtime, title, trailerUrl, MBitem["Id"])) + + #### UPDATE THE MOVIE ##### else: - shortplot = None + pathsql="update movie SET c00 = ?, c01 = ?, c02 = ?, c05 = ?, c07 = ?, c10 = ?, c11 = ?, c16 = ?, c19 = ?, embyId= ? WHERE idMovie = ?" + cursor.execute(pathsql, (title, plot, shortplot, rating, year, sorttitle, runtime, title, trailerUrl, MBitem["Id"], movieid)) - trailerUrl = None - if MBitem.get("LocalTrailerCount") != None and MBitem.get("LocalTrailerCount") > 0: - itemTrailerUrl = "%s/mediabrowser/Users/%s/Items/%s/LocalTrailers?format=json" % (server, userid, MBitem.get("Id")) - jsonData = downloadUtils.downloadUrl(itemTrailerUrl) - if(jsonData != ""): - trailerItem = jsonData - if trailerItem[0][u'LocationType'] == "FileSystem": - trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0][u'Id'], trailerItem[0]) - trailerUrl = utils.convertEncoding(trailerUrl) + #update or insert actors + self.AddActorsToMedia(movieid,MBitem.get("People"),"movie", connection, cursor) - #create the movie - cursor.execute("select coalesce(max(idMovie),0) as movieid from movie") - movieid = cursor.fetchone()[0] - movieid = movieid + 1 - pathsql="insert into movie(idMovie, idFile, c00, c01, c02, c05, c07, c09, c10, c11, c16, c19) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - - cursor.execute(pathsql, (movieid, fileid, title, plot, shortplot, rating, year, MBitem["Id"], sorttitle, runtime, title, trailerUrl)) - - try: - connection.commit() - utils.logMsg("Emby","Added movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"]) - except: - utils.logMsg("Emby","Error adding movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"]) - actionPerformed = False - + #commit changes and return the id + connection.commit() + return movieid + def addMusicVideoToKodiLibrary( self, MBitem, connection, cursor ): #adds a musicvideo to Kodi by directly inserting it to connectionthe DB while there is no addMusicVideo available on the json API @@ -716,13 +516,8 @@ class WriteKodiDB(): else: dateadded = None - # we need to store both the path and the filename seperately in the kodi db so we split them up - if "\\" in playurl: - filename = playurl.rsplit("\\",1)[-1] - path = playurl.replace(filename,"") - elif "/" in playurl: - filename = playurl.rsplit("/",1)[-1] - path = playurl.replace(filename,"") + path = "plugin://plugin.video.emby/musicvideos/" + filename = "plugin://plugin.video.emby/musicvideos/?mode=play&id=" + MBitem["Id"] #create the path cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) @@ -770,17 +565,20 @@ class WriteKodiDB(): utils.logMsg("Emby","Error adding musicvideo to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"]) actionPerformed = False - def addEpisodeToKodiLibrary(self, MBitem, connection, cursor): + def addOrUpdateEpisodeToKodiLibrary(self, embyId, showid, connection, cursor): - #adds a Episode to Kodi by directly inserting it to the DB while there is no addEpisode available on the json API - #TODO: PR at Kodi team for a addEpisode endpoint on their API + # If the episode already exist in the local Kodi DB we'll perform a full item update + # If the item doesn't exist, we'll add it to the database - # first check the episode is not already in the DB using the Emby ID which is stored in c20 - cursor.execute("SELECT idEpisode FROM episode WHERE c20 = ?",(MBitem["Id"],)) + MBitem = ReadEmbyDB().getFullItem(embyId) + + cursor.execute("SELECT idEpisode FROM episode WHERE embyId = ?",(MBitem["Id"],)) result = cursor.fetchone() if result != None: utils.logMsg("Emby", "Episode already exists in DB : " + MBitem["Id"] + " - " + MBitem["Name"], 2) - return + episodeid = result[0] + else: + episodeid = None addon = xbmcaddon.Addon(id='plugin.video.emby') port = addon.getSetting('port') @@ -790,83 +588,7 @@ class WriteKodiDB(): timeInfo = API().getTimeInfo(MBitem) userData=API().getUserData(MBitem) - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - playurl = utils.convertEncoding(playurl) - - if MBitem.get("DateCreated") != None: - dateadded = MBitem["DateCreated"].replace("T"," ") - dateadded = dateadded.split(".")[0] - else: - dateadded = None - - if userData.get("LastPlayedDate") != None: - lastplayed = userData.get("LastPlayedDate") - else: - lastplayed = None - - # we need to store both the path and the filename seperately in the kodi db so we split them up - if "\\" in playurl: - filename = playurl.rsplit("\\",1)[-1] - path = playurl.replace(filename,"") - elif "/" in playurl: - filename = playurl.rsplit("/",1)[-1] - path = playurl.replace(filename,"") - - #create the new path - return id if already exists - cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) - result = cursor.fetchone() - if result != None: - pathid = result[0] - if result == None: - cursor.execute("select coalesce(max(idPath),0) as pathid from path") - pathid = cursor.fetchone()[0] - pathid = pathid + 1 - pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" - cursor.execute(pathsql, (pathid,path,None,None,1)) - - playcount = None - if userData.get("PlayCount") == "1": - playcount = 1 - - #create the file if not exists - cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,)) - result = cursor.fetchone() - if result != None: - fileid = result[0] - if result == None: - cursor.execute("select coalesce(max(idFile),0) as fileid from files") - fileid = cursor.fetchone()[0] - fileid = fileid + 1 - sql="INSERT OR REPLACE into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)" - cursor.execute(sql, (fileid,pathid,filename,playcount,lastplayed,dateadded)) - - #get the showid - cursor.execute("SELECT idShow as showid FROM tvshow WHERE c12 = ?",(MBitem["SeriesId"],)) - result = cursor.fetchone() - showid = -1 - if(result == None): - utils.logMsg("Emby","Error adding episode to Kodi Library, couldn't find show - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) - actionPerformed = False - return False - else: - showid = result[0] - - # check season - season = 0 - if MBitem.get("ParentIndexNumber") != None: - season = int(MBitem.get("ParentIndexNumber")) - else: - utils.logMsg("Emby","Error adding episode to Kodi Library, no ParentIndexNumber - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) - return False - - cursor.execute("SELECT idSeason FROM seasons WHERE idShow = ? and season = ?",(showid, season)) - result = cursor.fetchone() - if(result == None): - utils.logMsg("Emby","Error adding episode to Kodi Library, season does not exist - ShowId: " + str(showid) + " SeasonNo: " + str(season) + " EmbyId: " + MBitem["Id"] + " Name: " + MBitem["Name"]) - actionPerformed = False - return False - - # build info + ###### episode properties ################ episode = 0 if MBitem.get("IndexNumber") != None: episode = int(MBitem.get("IndexNumber")) @@ -881,25 +603,93 @@ class WriteKodiDB(): else: premieredate = None - #create the episode - cursor.execute("select coalesce(max(idEpisode),0) as episodeid from episode") - episodeid = cursor.fetchone()[0] - episodeid = episodeid + 1 - pathsql = "INSERT into episode(idEpisode, idFile, c00, c01, c03, c05, c09, c20, c12, c13, c14, idShow, c15, c16) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cursor.execute(pathsql, (episodeid, fileid, title, plot, rating, premieredate, runtime, MBitem["Id"], season, episode, title, showid, "-1", "-1")) + if MBitem.get("DateCreated") != None: + dateadded = MBitem["DateCreated"].replace("T"," ") + dateadded = dateadded.split(".")[0] + else: + dateadded = None + + if userData.get("LastPlayedDate") != None: + lastplayed = userData.get("LastPlayedDate") + else: + lastplayed = None + + playcount = None + if userData.get("PlayCount") == "1": + playcount = 1 + + #### ADD OR UPDATE THE FILE AND PATH ########### + #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY + path = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/" + filename = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/?id=" MBitem["Id"] + "&mode=play" + + #create the new path - return id if already exists + cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) + result = cursor.fetchone() + if result != None: + pathid = result[0] + if result == None: + cursor.execute("select coalesce(max(idPath),0) as pathid from path") + pathid = cursor.fetchone()[0] + pathid = pathid + 1 + pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" + cursor.execute(pathsql, (pathid,path,None,None,1)) + + #create the file if not exists + cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,)) + result = cursor.fetchone() + if result != None: + fileid = result[0] + if result == None: + cursor.execute("select coalesce(max(idFile),0) as fileid from files") + fileid = cursor.fetchone()[0] + fileid = fileid + 1 + sql="INSERT OR REPLACE into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)" + cursor.execute(sql, (fileid,pathid,filename,playcount,lastplayed,dateadded)) + + # safety check: check season first + season = 0 + if MBitem.get("ParentIndexNumber") != None: + season = int(MBitem.get("ParentIndexNumber")) + else: + utils.logMsg("Emby","SKIP adding episode to Kodi Library, no ParentIndexNumber - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) + return False + + cursor.execute("SELECT idSeason FROM seasons WHERE idShow = ? and season = ?",(showid, season)) + result = cursor.fetchone() + if(result == None): + #update seasons first + self.updateSeasons(MBitem["SeriesId"], showid, connection, cursor) + + # ADD EPISODE TO KODI + if episodeid == None: + + #create the episode + cursor.execute("select coalesce(max(idEpisode),0) as episodeid from episode") + episodeid = cursor.fetchone()[0] + episodeid = episodeid + 1 + pathsql = "INSERT into episode(idEpisode, idFile, c00, c01, c03, c05, c09, c12, c13, c14, idShow, c15, c16, embyId) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + cursor.execute(pathsql, (episodeid, fileid, title, plot, rating, premieredate, runtime, season, episode, title, showid, "-1", "-1", MBitem["Id"])) + + # UPDATE THE EPISODE IN KODI (for now, we just send in all data) + else: + pathsql = "UPDATE episode SET c00 = ?, c01 = ?, c03 = ?, c05 = ?, c09 = ?, c12 = ?, c13 = ?, c14 = ?, c15 = ?, c16 = ?, embyId = ? WHERE idEpisode = ?" + cursor.execute(pathsql, title, plot, rating, premieredate, runtime, season, episode, title, MBitem["Id"], episodeid) + + #update or insert actors + self.AddActorsToMedia(episodeid,MBitem.get("People"),"episode", connection, cursor) try: connection.commit() - utils.logMsg("Emby","Added episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) + utils.logMsg("Emby","Added or updated episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) except: - utils.logMsg("Emby","Error adding episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) + utils.logMsg("Emby","Error adding/updating episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"]) actionPerformed = False - def deleteMovieFromKodiLibrary(self, id ): - kodiItem = ReadKodiDB().getKodiMovie(id) - utils.logMsg("deleting movie from Kodi library",id) - if kodiItem != None: - xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMovie", "params": { "movieid": %i}, "id": 1 }' %(kodiItem["movieid"])) + def deleteMovieFromKodiLibrary(self, id, connection, cursor ): + utils.logMsg("deleting movie from Kodi library --> ",id) + cursor.execute("DELETE FROM movie WHERE embyId = ?", (id,)) + connection.commit() def deleteMusicVideoFromKodiLibrary(self, id ): utils.logMsg("deleting musicvideo from Kodi library",id) @@ -907,129 +697,120 @@ class WriteKodiDB(): if kodiItem != None: xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMusicVideo", "params": { "musicvideoid": %i}, "id": 1 }' %(kodiItem["musicvideoid"])) - def deleteEpisodeFromKodiLibrary(self, episodeid, tvshowid ): - utils.logMsg("deleting episode from Kodi library",episodeid) - episode = ReadKodiDB().getKodiEpisodeByMbItem(episodeid, tvshowid) - if episode != None: - WINDOW = xbmcgui.Window( 10000 ) - xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(episode["episodeid"])) - - utils.logMsg("episode deleted succesfully!",episodeid) - else: - utils.logMsg("episode not found in kodi DB",episodeid) - - def deleteEpisodeFromKodiLibraryByMbId(self, id ): - utils.logMsg("deleting episode from Kodi library", id) - kodiItem = ReadKodiDB().getKodiEpisodeByMbItemEx(id) - if kodiItem != None: - xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(kodiItem["episodeid"])) - utils.logMsg("episode deleted succesfully!", id) - else: - utils.logMsg("episode not found in kodi DB", id) - - def addTVShowToKodiLibrary( self, MBitem, connection, cursor ): - #adds a Tvshow to Kodi by directly inserting it to the DB while there is no addTvShow available on the json API - #TODO: PR at Kodi team for a addTvShow endpoint on their API + def deleteEpisodeFromKodiLibrary(self, id, connection, cursor ): + utils.logMsg("deleting episode from Kodi library --> ",id) + cursor.execute("DELETE FROM episode WHERE embyId = ?", (id,)) + connection.commit() + + def addOrUpdateTvShowToKodiLibrary( self, embyId, connection, cursor, viewTag ): addon = xbmcaddon.Addon(id='plugin.video.emby') port = addon.getSetting('port') host = addon.getSetting('ipaddress') server = host + ":" + port + MBitem = ReadEmbyDB().getFullItem(embyId) + timeInfo = API().getTimeInfo(MBitem) userData=API().getUserData(MBitem) thumbPath = API().getArtwork(MBitem, "Primary") - playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem) - #make sure that the path always ends with a slash - path = utils.convertEncoding(playurl + "/") + # If the item already exist in the local Kodi DB we'll perform a full item update + # If the item doesn't exist, we'll add it to the database + + cursor.execute("SELECT idMovie FROM movie WHERE embyId = ?",(MBitem["Id"],)) + result = cursor.fetchone() + if result != None: + showid = result[0] + else: + showid = None + + #### TV SHOW DETAILS ######### if MBitem.get("DateCreated") != None: dateadded = MBitem["DateCreated"].replace("T"," ") dateadded = dateadded.replace(".0000000Z","") else: dateadded = None - - #create the tv show path - cursor.execute("select coalesce(max(idPath),0) as pathid from path") - pathid = cursor.fetchone()[0] - pathid = pathid + 1 - pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" - cursor.execute(pathsql, (pathid,path,None,None,1)) - #create toplevel path as monitored source - needed for things like actors and stuff to work (no clue why) - if "\\" in path: - toplevelpathstr = path.rsplit("\\",2)[1] - toplevelpath = path.replace(toplevelpathstr + "\\","") - elif "/" in path: - toplevelpathstr = path.rsplit("/",2)[1] - toplevelpath = path.replace(toplevelpathstr + "/","") - cursor.execute("SELECT idPath as tlpathid FROM path WHERE strPath = ?",(toplevelpath,)) - result = cursor.fetchone() - if result == None: - cursor.execute("select coalesce(max(idPath),0) as tlpathid from path") - tlpathid = cursor.fetchone()[0] - tlpathid = pathid + 1 - pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" - cursor.execute(pathsql, (tlpathid,toplevelpath,"tvshows","metadata.local",1)) + path = "plugin://plugin.video.emby/tvshows/" + MBitem["Id"] + "/" - - runtime = int(timeInfo.get('Duration'))*60 - plot = utils.convertEncoding(API().getOverview(MBitem)) - title = utils.convertEncoding(MBitem["Name"]) - sorttitle = utils.convertEncoding(MBitem["SortName"]) - rating = MBitem.get("CommunityRating") - #create the tvshow - cursor.execute("select coalesce(max(idShow),0) as showid from tvshow") - showid = cursor.fetchone()[0] - showid = pathid + 1 - pathsql="insert into tvshow(idShow, c00, c01, c04, c09, c12, c15) values(?, ?, ?, ?, ?, ?, ?)" - cursor.execute(pathsql, (showid, title, plot, rating, title, MBitem["Id"], sorttitle)) + #### ADD THE TV SHOW TO KODI ############## + if showid == None: + #create toplevel path as monitored source - needed for things like actors and stuff to work (no clue why) + toplevelpath = "plugin://plugin.video.emby/tvshows/" + cursor.execute("SELECT idPath as tlpathid FROM path WHERE strPath = ?",(toplevelpath,)) + result = cursor.fetchone() + if result == None: + cursor.execute("select coalesce(max(idPath),0) as tlpathid from path") + tlpathid = cursor.fetchone()[0] + tlpathid = tlpathid + 1 + pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" + cursor.execute(pathsql, (tlpathid,toplevelpath,"tvshows","metadata.local",1)) + else: + tlpathid = result[0] + + #create the tv show path + cursor.execute("select coalesce(max(idPath),0) as pathid from path") + pathid = cursor.fetchone()[0] + pathid = pathid + 1 + pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate, idParentPath) values(?, ?, ?, ?, ?, ?)" + cursor.execute(pathsql, (pathid,path,None,None,1,tlpathid)) + + runtime = int(timeInfo.get('Duration'))*60 + plot = utils.convertEncoding(API().getOverview(MBitem)) + title = utils.convertEncoding(MBitem["Name"]) + sorttitle = utils.convertEncoding(MBitem["SortName"]) + rating = MBitem.get("CommunityRating") + + #create the tvshow + cursor.execute("select coalesce(max(idShow),0) as showid from tvshow") + showid = cursor.fetchone()[0] + showid = pathid + 1 + pathsql="insert into tvshow(idShow, c00, c01, c04, c09, c15, embyId) values(?, ?, ?, ?, ?, ?, ?)" + cursor.execute(pathsql, (showid, title, plot, rating, title, sorttitle, MBitem["Id"])) + + #link the path + pathsql="insert into tvshowlinkpath(idShow,idPath) values(?, ?)" + cursor.execute(pathsql, (showid,pathid)) - #link the path - pathsql="insert into tvshowlinkpath(idShow,idPath) values(?, ?)" - cursor.execute(pathsql, (showid,pathid)) - - try: - connection.commit() - utils.logMsg("Emby","Added TV Show to Kodi Library: " + MBitem["Id"] + " - " + MBitem["Name"]) - except: - utils.logMsg("Emby","Error adding tvshow to Kodi Library: " + MBitem["Id"] + " - " + MBitem["Name"]) - actionPerformed = False + #### UPDATE THE TV SHOW ############# + else: + pathsql="UPDATE tvshow SET (c00 = ?, c01 = ?, c04 = ?, c09 = ?, c15 = ?, embyId = ? WHERE idShow = ?" + cursor.execute(pathsql, title, plot, rating, title, sorttitle, MBitem["Id"], showid) + + #update or insert actors + self.AddActorsToMedia(showid,MBitem.get("People"),"tvshow", connection, cursor) - def deleteTVShowFromKodiLibrary(self, id): - xbmc.sleep(sleepVal) - kodiItem = ReadKodiDB().getKodiTVShow(id) - utils.logMsg("deleting tvshow from Kodi library ", "Emby ID : " + id) - - if kodiItem != None: - utils.logMsg("deleting tvshow from Kodi library ", str(kodiItem)) - kodiId = kodiItem["tvshowid"] - utils.logMsg("deleting tvshow from Kodi library ", "Kodi ID : " + str(kodiId)) - xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveTVShow", "params": { "tvshowid": %i}, "id": 1 }' %(kodiId)) + #update season details + self.updateSeasons(MBitem["Id"], showid, connection, cursor) + + #commit changes and return the id + connection.commit() + return showid + + def deleteTVShowFromKodiLibrary(self, id, connection, cursor): + utils.logMsg("deleting tvshow from Kodi library --> ",id) + cursor.execute("DELETE FROM tvshow WHERE embyId = ?", (id,)) + connection.commit() - def updateSeasons(self,MBitem, KodiItem, connection, cursor): - #use sqlite to set the season details because no method in API available for this - tvshowid = KodiItem["tvshowid"] - - #connection = utils.KodiSQL() - #cursor = connection.cursor() + def updateSeasons(self,embyTvShowId, kodiTvShowId, connection, cursor): - seasonData = ReadEmbyDB().getTVShowSeasons(MBitem["Id"]) + seasonData = ReadEmbyDB().getTVShowSeasons(embyTvShowId) if seasonData != None: for season in seasonData: seasonNum = season.get("IndexNumber") if seasonNum != None and seasonNum >= 0 and seasonNum <= 1000: - cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(tvshowid, seasonNum)) + cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(kodiTvShowId, seasonNum)) result = cursor.fetchone() if result == None: #create the season cursor.execute("select coalesce(max(idSeason),0) as seasonid from seasons") seasonid = cursor.fetchone()[0] seasonid = seasonid + 1 - cursor.execute("INSERT into seasons(idSeason, idShow, season) values(?, ?, ?)", (seasonid, tvshowid, seasonNum)) + cursor.execute("INSERT into seasons(idSeason, idShow, season) values(?, ?, ?)", (seasonid, kodiTvShowId, seasonNum)) else: seasonid = result[0] @@ -1043,7 +824,6 @@ class WriteKodiDB(): imageUrl = API().getArtwork(season, "Banner") self.updateSeasonArt(imageUrl, seasonid, "banner", cursor) - connection.commit() def updateSeasonArt(self, imageUrl, seasonid, imageType, cursor): updateDone = False @@ -1129,136 +909,9 @@ class WriteKodiDB(): return changes ''' - - def setKodiFilename(self, id, oldFileName, newFileName, fileType, mbId, connection, cursor): - #use sqlite to set the filename in DB -- needed to avoid problems with resumepoints etc - #return True if any action is performed, False if no action is performed - #todo --> submit PR to kodi team to get this added to the jsonrpc api - #todo --> extend support for musicvideos - - actionPerformed = False - - oldFileName = utils.convertEncoding(oldFileName) - newFileName = utils.convertEncoding(newFileName) - - # this is required to make sure the paths match - oldFileName = oldFileName.replace("\\", "/") - - # only perform changes if the path actually differs - if oldFileName != newFileName: - - # xbmc.sleep(sleepVal) - #connection = utils.KodiSQL() - #cursor = connection.cursor() - utils.logMsg("Emby","setting filename in kodi db..." + fileType + ": " + str(id)) - utils.logMsg("Emby","old filename -->" + oldFileName) - utils.logMsg("Emby","new filename -->" + newFileName) - - ######### PROCESS TV SHOW ############ - if fileType == "tvshow": - - if newFileName.startswith("http"): - newFileName = "plugin://plugin.video.emby/" - - #for tvshows we only store the path in DB - cursor.execute("SELECT idPath as pathid FROM tvshowlinkpath WHERE idShow = ?",(id,)) - result = cursor.fetchone() - pathid = result[0] - cursor.execute("UPDATE path SET strPath = ?, noUpdate = ?, idParentPath = ? WHERE idPath = ?", (newFileName,1,None,pathid)) - - else: - # we need to store both the path and the filename seperately in the kodi db so we split them up - - if newFileName.startswith("http"): - #transcoding or play from stream - path = "plugin://plugin.video.emby/" - filename = "plugin://plugin.video.emby/?id=" + mbId + "&mode=play" - - else: - # direct play - if "\\" in newFileName: - filename = newFileName.rsplit("\\",1)[-1] - path = newFileName.replace(filename,"") - elif "/" in newFileName: - filename = newFileName.rsplit("/",1)[-1] - path = newFileName.replace(filename,"") - - - ######### PROCESS EPISODE ############ - if fileType == "episode": - - #get the file and the current path id - cursor.execute("SELECT idFile as fileid FROM episode WHERE idEpisode = ?",(id,)) - result = cursor.fetchone() - fileid = result[0] - - #create the new path - return id if already exists - cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) - result = cursor.fetchone() - if result != None: - pathid = result[0] - if result == None: - cursor.execute("select coalesce(max(idPath),0) as pathid from path") - pathid = cursor.fetchone()[0] - pathid = pathid + 1 - pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)" - cursor.execute(pathsql, (pathid,path,None,None,1)) - - #set the new path and filename to the episode - cursor.execute("UPDATE files SET idPath = ?, strFilename = ? WHERE idFile = ?", (pathid,filename,fileid)) - - ######### PROCESS MOVIE ############ - if fileType == "movie": - cursor.execute("SELECT idFile as fileid FROM movie WHERE idMovie = ?",(id,)) - result = cursor.fetchone() - fileid = result[0] - #write the new filename to the DB - cursor.execute("UPDATE files SET strFilename = ? WHERE idFile = ?", (filename,fileid)) - #set the new path - cursor.execute("SELECT idPath as pathid FROM files WHERE idFile = ?",(fileid,)) - result = cursor.fetchone() - pathid = result[0] - cursor.execute("UPDATE path SET strPath = ?, strContent = ?, strScraper = ?, noUpdate = ?, idParentPath = ? WHERE idPath = ?", (path, "movies", "metadata.local", 1, None, pathid)) - - try: - connection.commit() - actionPerformed = True - except: - utils.logMsg("Emby","Error setting filename in kodi db for: " + fileType + ": " + str(id)) - actionPerformed = False - - return actionPerformed - - def AddActorsToMedia(self, KodiItem, people, mediatype, connection, cursor): - #use sqlite to set add the actors while json api doesn't support this yet - #todo --> submit PR to kodi team to get this added to the jsonrpc api - + def AddActorsToMedia(self, id, people, mediatype, connection, cursor): downloadUtils = DownloadUtils() - if mediatype == "movie": - id = KodiItem["movieid"] - if mediatype == "tvshow": - id = KodiItem["tvshowid"] - if mediatype == "episode": - id = KodiItem["episodeid"] - - currentcast = list() - if KodiItem["cast"] != None: - for cast in KodiItem["cast"]: - currentcast.append(cast["name"]) - - needsUpdate = False - if(people != None): - for person in people: - if(person.get("Type") == "Actor"): - if person.get("Name") not in currentcast: - needsUpdate = True - break - - if(needsUpdate == False): - return False - - utils.logMsg("AddActorsToMedia", "List needs updating") kodiVersion = 14 if xbmc.getInfoLabel("System.BuildVersion").startswith("15"): @@ -1267,61 +920,53 @@ class WriteKodiDB(): if(people != None): for person in people: if(person.get("Type") == "Actor"): - if person.get("Name") not in currentcast: - utils.logMsg("AddActorsToMedia", "Processing : " + person.get("Name")) - Name = person.get("Name") - Role = person.get("Role") - actorid = None - Thumb = downloadUtils.imageUrl(person.get("Id"), "Primary", 0, 400, 400) + utils.logMsg("AddActorsToMedia", "Processing : " + person.get("Name")) + Name = person.get("Name") + Role = person.get("Role") + actorid = None + Thumb = downloadUtils.imageUrl(person.get("Id"), "Primary", 0, 400, 400) + if kodiVersion == 15: + # Kodi Isengard database # + if Thumb != None: + Thumb = "" + Thumb + "" + cursor.execute("SELECT actor_id as actorid FROM actor WHERE name = ?",(Name,)) + else: + # Kodi Gotham or Helix database # + cursor.execute("SELECT idActor as actorid FROM actors WHERE strActor = ?",(Name,)) + result = cursor.fetchone() + if result != None: + actorid = result[0] + if actorid == None: if kodiVersion == 15: # Kodi Isengard database # - if Thumb != None: - Thumb = "" + Thumb + "" - cursor.execute("SELECT actor_id as actorid FROM actor WHERE name = ?",(Name,)) + cursor.execute("select coalesce(max(actor_id),0) as actorid from actor") + actorid = cursor.fetchone()[0] + actorid = actorid + 1 + peoplesql="insert into actor(actor_id, name, art_urls) values(?, ?, ?)" else: # Kodi Gotham or Helix database # - cursor.execute("SELECT idActor as actorid FROM actors WHERE strActor = ?",(Name,)) - result = cursor.fetchone() - if result != None: - actorid = result[0] - if actorid == None: - if kodiVersion == 15: - # Kodi Isengard database # - cursor.execute("select coalesce(max(actor_id),0) as actorid from actor") - actorid = cursor.fetchone()[0] - actorid = actorid + 1 - peoplesql="insert into actor(actor_id, name, art_urls) values(?, ?, ?)" - else: - # Kodi Gotham or Helix database # - cursor.execute("select coalesce(max(idActor),0) as actorid from actors") - actorid = cursor.fetchone()[0] - actorid = actorid + 1 - peoplesql="insert into actors(idActor, strActor, strThumb) values(?, ?, ?)" - cursor.execute(peoplesql, (actorid,Name,Thumb)) - - if kodiVersion == 15: - # Kodi Isengard database # - peoplesql="INSERT OR REPLACE into actor_link(actor_id, media_id, media_type, role, cast_order) values(?, ?, ?, ?, ?)" - cursor.execute(peoplesql, (actorid, id, mediatype, Role, None)) - else: - # Kodi Gotham or Helix database # - if mediatype == "movie": - peoplesql="INSERT OR REPLACE into actorlinkmovie(idActor, idMovie, strRole, iOrder) values(?, ?, ?, ?)" - if mediatype == "tvshow": - peoplesql="INSERT OR REPLACE into actorlinktvshow(idActor, idShow, strRole, iOrder) values(?, ?, ?, ?)" - if mediatype == "episode": - peoplesql="INSERT OR REPLACE into actorlinkepisode(idActor, idEpisode, strRole, iOrder) values(?, ?, ?, ?)" - cursor.execute(peoplesql, (actorid,id,Role,None)) - - connection.commit() - #cursor.close() - - return True - + cursor.execute("select coalesce(max(idActor),0) as actorid from actors") + actorid = cursor.fetchone()[0] + actorid = actorid + 1 + peoplesql="insert into actors(idActor, strActor, strThumb) values(?, ?, ?)" + cursor.execute(peoplesql, (actorid,Name,Thumb)) + + if kodiVersion == 15: + # Kodi Isengard database # + peoplesql="INSERT OR REPLACE into actor_link(actor_id, media_id, media_type, role, cast_order) values(?, ?, ?, ?, ?)" + cursor.execute(peoplesql, (actorid, id, mediatype, Role, None)) + else: + # Kodi Gotham or Helix database # + if mediatype == "movie": + peoplesql="INSERT OR REPLACE into actorlinkmovie(idActor, idMovie, strRole, iOrder) values(?, ?, ?, ?)" + if mediatype == "tvshow": + peoplesql="INSERT OR REPLACE into actorlinktvshow(idActor, idShow, strRole, iOrder) values(?, ?, ?, ?)" + if mediatype == "episode": + peoplesql="INSERT OR REPLACE into actorlinkepisode(idActor, idEpisode, strRole, iOrder) values(?, ?, ?, ?)" + cursor.execute(peoplesql, (actorid,id,Role,None)) + + def addBoxsetToKodiLibrary(self, boxset, connection, cursor): - #use sqlite to set add the set - #connection = utils.KodiSQL() - #cursor = connection.cursor() strSet = boxset["Name"] # check if exists @@ -1365,7 +1010,7 @@ class WriteKodiDB(): if result != None: setid = result[0] connection.commit() - #cursor.close() + return True diff --git a/service.py b/service.py index 55c8b664..72d4e045 100644 --- a/service.py +++ b/service.py @@ -115,12 +115,10 @@ class Service(): self.logMsg("Doing_Db_Sync: syncDatabase (Started)") libSync = librarySync.syncDatabase() self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync)) - countSync = librarySync.updatePlayCounts() - self.logMsg("Doing_Db_Sync: updatePlayCounts (Finished) " + str(countSync)) # Force refresh newly set thumbnails xbmc.executebuiltin("UpdateLibrary(video)") - if(libSync and countSync): + if(libSync): startupComplete = True else: if self.KodiMonitor.waitForAbort(10):