changes to use native kodi db for inserts
This commit is contained in:
parent
8ec2d7d33b
commit
5f8e5105bb
6 changed files with 520 additions and 482 deletions
|
@ -99,8 +99,6 @@ class LibrarySync():
|
||||||
|
|
||||||
for view in views:
|
for view in views:
|
||||||
|
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
#process new movies
|
#process new movies
|
||||||
allMB3Movies = ReadEmbyDB().getMovies(view.get('id'), True, fullsync)
|
allMB3Movies = ReadEmbyDB().getMovies(view.get('id'), True, fullsync)
|
||||||
allKodiIds = set(ReadKodiDB().getKodiMoviesIds(True))
|
allKodiIds = set(ReadKodiDB().getKodiMoviesIds(True))
|
||||||
|
@ -126,7 +124,6 @@ class LibrarySync():
|
||||||
|
|
||||||
if item["Id"] not in allKodiIds:
|
if item["Id"] not in allKodiIds:
|
||||||
WriteKodiDB().addMovieToKodiLibrary(item)
|
WriteKodiDB().addMovieToKodiLibrary(item)
|
||||||
updateNeeded = True
|
|
||||||
totalItemsAdded += 1
|
totalItemsAdded += 1
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
|
@ -138,19 +135,6 @@ class LibrarySync():
|
||||||
pDialog.update(percentage, progressTitle, "Adding Movie: " + str(count))
|
pDialog.update(percentage, progressTitle, "Adding Movie: " + str(count))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
#initiate library update and wait for finish before processing any updates
|
|
||||||
if updateNeeded:
|
|
||||||
if(pDialog != None):
|
|
||||||
pDialog.update(0, "Processing New Items", "Importing STRM Files")
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.close()
|
|
||||||
|
|
||||||
self.doKodiLibraryUpdate(False, pDialog)
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.create('Sync DB', 'Sync DB')
|
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -228,8 +212,6 @@ class LibrarySync():
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cleanNeeded = False
|
|
||||||
|
|
||||||
# process any deletes only at fullsync
|
# process any deletes only at fullsync
|
||||||
if fullsync:
|
if fullsync:
|
||||||
allKodiIds = ReadKodiDB().getKodiMoviesIds(True)
|
allKodiIds = ReadKodiDB().getKodiMoviesIds(True)
|
||||||
|
@ -238,16 +220,11 @@ class LibrarySync():
|
||||||
if not kodiId in allEmbyMovieIds:
|
if not kodiId in allEmbyMovieIds:
|
||||||
WINDOW.setProperty(kodiId,"deleted")
|
WINDOW.setProperty(kodiId,"deleted")
|
||||||
WriteKodiDB().deleteMovieFromKodiLibrary(kodiId)
|
WriteKodiDB().deleteMovieFromKodiLibrary(kodiId)
|
||||||
cleanNeeded = True
|
|
||||||
totalItemsDeleted += 1
|
totalItemsDeleted += 1
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#initiate library clean and wait for finish before processing any updates
|
|
||||||
if cleanNeeded:
|
|
||||||
self.doKodiLibraryUpdate(True, pDialog)
|
|
||||||
|
|
||||||
# display notification if set up
|
# display notification if set up
|
||||||
notificationString = ""
|
notificationString = ""
|
||||||
if(totalItemsAdded > 0):
|
if(totalItemsAdded > 0):
|
||||||
|
@ -308,8 +285,6 @@ class LibrarySync():
|
||||||
if latestMBEpisodes != None:
|
if latestMBEpisodes != None:
|
||||||
allKodiTvShowsIds = set(ReadKodiDB().getKodiTvShowsIds(True))
|
allKodiTvShowsIds = set(ReadKodiDB().getKodiTvShowsIds(True))
|
||||||
|
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
if(pDialog != None):
|
if(pDialog != None):
|
||||||
pDialog.update(0, progressTitle)
|
pDialog.update(0, progressTitle)
|
||||||
total = len(latestMBEpisodes) + 1
|
total = len(latestMBEpisodes) + 1
|
||||||
|
@ -339,7 +314,6 @@ class LibrarySync():
|
||||||
#no match so we have to create it
|
#no match so we have to create it
|
||||||
print "creating episode in incremental sync!"
|
print "creating episode in incremental sync!"
|
||||||
WriteKodiDB().addEpisodeToKodiLibrary(episode)
|
WriteKodiDB().addEpisodeToKodiLibrary(episode)
|
||||||
updateNeeded = True
|
|
||||||
progressAction = "Adding"
|
progressAction = "Adding"
|
||||||
totalItemsAdded += 1
|
totalItemsAdded += 1
|
||||||
|
|
||||||
|
@ -352,11 +326,6 @@ class LibrarySync():
|
||||||
pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count))
|
pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
#initiate library update and wait for finish before processing any updates
|
|
||||||
if updateNeeded:
|
|
||||||
self.doKodiLibraryUpdate(False, pDialog)
|
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
#process updates
|
#process updates
|
||||||
if(pDialog != None):
|
if(pDialog != None):
|
||||||
progressTitle = "Sync DB : Processing Episodes"
|
progressTitle = "Sync DB : Processing Episodes"
|
||||||
|
@ -400,7 +369,6 @@ class LibrarySync():
|
||||||
|
|
||||||
tvShowData = ReadEmbyDB().getTVShows(True,True)
|
tvShowData = ReadEmbyDB().getTVShows(True,True)
|
||||||
allKodiIds = set(ReadKodiDB().getKodiTvShowsIds(True))
|
allKodiIds = set(ReadKodiDB().getKodiTvShowsIds(True))
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
@ -420,7 +388,6 @@ class LibrarySync():
|
||||||
progMessage = "Processing"
|
progMessage = "Processing"
|
||||||
if item["Id"] not in allKodiIds:
|
if item["Id"] not in allKodiIds:
|
||||||
WriteKodiDB().addTVShowToKodiLibrary(item)
|
WriteKodiDB().addTVShowToKodiLibrary(item)
|
||||||
updateNeeded = True
|
|
||||||
totalItemsAdded += 1
|
totalItemsAdded += 1
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
|
@ -479,7 +446,6 @@ class LibrarySync():
|
||||||
if ReadKodiDB().getKodiEpisodeByMbItem(item["Id"],tvshow) == None:
|
if ReadKodiDB().getKodiEpisodeByMbItem(item["Id"],tvshow) == None:
|
||||||
#no match so we have to create it
|
#no match so we have to create it
|
||||||
WriteKodiDB().addEpisodeToKodiLibrary(item)
|
WriteKodiDB().addEpisodeToKodiLibrary(item)
|
||||||
updateNeeded = True
|
|
||||||
progressAction = "Adding"
|
progressAction = "Adding"
|
||||||
totalItemsAdded += 1
|
totalItemsAdded += 1
|
||||||
|
|
||||||
|
@ -494,19 +460,6 @@ class LibrarySync():
|
||||||
|
|
||||||
showCurrent += 1
|
showCurrent += 1
|
||||||
|
|
||||||
#initiate library update and wait for finish before processing any updates
|
|
||||||
if updateNeeded:
|
|
||||||
if(pDialog != None):
|
|
||||||
pDialog.update(0, "Processing New Items", "Importing STRM Files")
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.close()
|
|
||||||
|
|
||||||
self.doKodiLibraryUpdate(False, pDialog)
|
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.create('Sync DB', 'Sync DB')
|
|
||||||
|
|
||||||
if(pDialog != None):
|
if(pDialog != None):
|
||||||
progressTitle = "Sync DB : Processing TV Shows"
|
progressTitle = "Sync DB : Processing TV Shows"
|
||||||
|
@ -602,8 +555,6 @@ class LibrarySync():
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cleanNeeded = False
|
|
||||||
|
|
||||||
# DELETES -- EPISODES
|
# DELETES -- EPISODES
|
||||||
# process any deletes only at fullsync
|
# process any deletes only at fullsync
|
||||||
allMB3EpisodeIds = set(allMB3EpisodeIds)
|
allMB3EpisodeIds = set(allMB3EpisodeIds)
|
||||||
|
@ -611,26 +562,20 @@ class LibrarySync():
|
||||||
if episode.get('episodeid') not in allMB3EpisodeIds:
|
if episode.get('episodeid') not in allMB3EpisodeIds:
|
||||||
WINDOW.setProperty("embyid" + str(episode.get('episodeid')),"deleted")
|
WINDOW.setProperty("embyid" + str(episode.get('episodeid')),"deleted")
|
||||||
WriteKodiDB().deleteEpisodeFromKodiLibrary(episode.get('episodeid'),episode.get('tvshowid'))
|
WriteKodiDB().deleteEpisodeFromKodiLibrary(episode.get('episodeid'),episode.get('tvshowid'))
|
||||||
cleanneeded = True
|
|
||||||
totalItemsDeleted += 1
|
totalItemsDeleted += 1
|
||||||
|
|
||||||
# DELETES -- TV SHOWS
|
# DELETES -- TV SHOWS
|
||||||
if fullsync:
|
if fullsync:
|
||||||
allLocaldirs, filesTVShows = xbmcvfs.listdir(tvLibrary)
|
allKodiShows = ReadKodiDB().getKodiTvShowsIds(True)
|
||||||
allMB3TVShows = set(allTVShows)
|
allMB3TVShows = set(allTVShows)
|
||||||
for dir in allLocaldirs:
|
for show in allKodiShows:
|
||||||
if not dir in allMB3TVShows:
|
if not show in allMB3TVShows:
|
||||||
WriteKodiDB().deleteTVShowFromKodiLibrary(dir)
|
WriteKodiDB().deleteTVShowFromKodiLibrary(dir)
|
||||||
cleanneeded = True
|
|
||||||
totalItemsDeleted += 1
|
totalItemsDeleted += 1
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#initiate library clean and wait for finish before processing any updates
|
|
||||||
if cleanNeeded:
|
|
||||||
self.doKodiLibraryUpdate(True, pDialog)
|
|
||||||
|
|
||||||
# display notification if set up
|
# display notification if set up
|
||||||
notificationString = ""
|
notificationString = ""
|
||||||
if(totalItemsAdded > 0):
|
if(totalItemsAdded > 0):
|
||||||
|
@ -680,8 +625,6 @@ class LibrarySync():
|
||||||
|
|
||||||
progressTitle = ""
|
progressTitle = ""
|
||||||
|
|
||||||
updateNeeded = False
|
|
||||||
|
|
||||||
#process new musicvideos
|
#process new musicvideos
|
||||||
allMB3MusicVideos = ReadEmbyDB().getMusicVideos(True, fullsync)
|
allMB3MusicVideos = ReadEmbyDB().getMusicVideos(True, fullsync)
|
||||||
allKodiIds = set(ReadKodiDB().getKodiMusicVideoIds(True))
|
allKodiIds = set(ReadKodiDB().getKodiMusicVideoIds(True))
|
||||||
|
@ -705,7 +648,6 @@ class LibrarySync():
|
||||||
|
|
||||||
if item["Id"] not in allKodiIds:
|
if item["Id"] not in allKodiIds:
|
||||||
WriteKodiDB().addMusicVideoToKodiLibrary(item)
|
WriteKodiDB().addMusicVideoToKodiLibrary(item)
|
||||||
updateNeeded = True
|
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
@ -716,19 +658,6 @@ class LibrarySync():
|
||||||
pDialog.update(percentage, progressTitle, "Adding Musicvideo: " + str(count))
|
pDialog.update(percentage, progressTitle, "Adding Musicvideo: " + str(count))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
#initiate library update and wait for finish before processing any updates
|
|
||||||
if updateNeeded:
|
|
||||||
if(pDialog != None):
|
|
||||||
pDialog.update(0, "Processing New Items", "Importing STRM Files")
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.close()
|
|
||||||
|
|
||||||
self.doKodiLibraryUpdate(False, pDialog)
|
|
||||||
|
|
||||||
if(pDialog != None and type(pDialog) == xbmcgui.DialogProgressBG):
|
|
||||||
pDialog.create('Sync DB', 'Sync DB')
|
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -750,7 +679,6 @@ class LibrarySync():
|
||||||
kodimusicvideo = None
|
kodimusicvideo = None
|
||||||
|
|
||||||
if(kodimusicvideo != None):
|
if(kodimusicvideo != None):
|
||||||
#WriteKodiDB().updateMusicVideoToKodiLibrary(item, kodimusicvideo)
|
|
||||||
WriteKodiDB().updateMusicVideoToKodiLibrary_Batched(item, kodimusicvideo)
|
WriteKodiDB().updateMusicVideoToKodiLibrary_Batched(item, kodimusicvideo)
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
|
@ -770,8 +698,6 @@ class LibrarySync():
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cleanNeeded = False
|
|
||||||
|
|
||||||
# process any deletes only at fullsync
|
# process any deletes only at fullsync
|
||||||
if fullsync:
|
if fullsync:
|
||||||
allKodiIds = ReadKodiDB().getKodiMusicVideoIds(True)
|
allKodiIds = ReadKodiDB().getKodiMusicVideoIds(True)
|
||||||
|
@ -779,33 +705,16 @@ class LibrarySync():
|
||||||
for kodiId in allKodiIds:
|
for kodiId in allKodiIds:
|
||||||
if not kodiId in allEmbyMusicVideoIds:
|
if not kodiId in allEmbyMusicVideoIds:
|
||||||
WriteKodiDB().deleteMusicVideoFromKodiLibrary(kodiId)
|
WriteKodiDB().deleteMusicVideoFromKodiLibrary(kodiId)
|
||||||
cleanNeeded = True
|
|
||||||
|
|
||||||
if(self.ShouldStop(pDialog)):
|
if(self.ShouldStop(pDialog)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#initiate library clean and wait for finish before processing any updates
|
|
||||||
if cleanNeeded:
|
|
||||||
self.doKodiLibraryUpdate(True, pDialog)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if(pDialog != None):
|
if(pDialog != None):
|
||||||
pDialog.close()
|
pDialog.close()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def doKodiLibraryUpdate(self, clean, prog):
|
|
||||||
#initiate library update and wait for finish before processing any updates
|
|
||||||
if clean:
|
|
||||||
xbmc.executebuiltin("CleanLibrary(video)")
|
|
||||||
else:
|
|
||||||
xbmc.executebuiltin("UpdateLibrary(video)")
|
|
||||||
xbmc.sleep(1000)
|
|
||||||
while (xbmc.getCondVisibility("Library.IsScanningVideo")):
|
|
||||||
if(self.ShouldStop(prog)):
|
|
||||||
return False
|
|
||||||
xbmc.sleep(1000)
|
|
||||||
|
|
||||||
def updatePlayCounts(self):
|
def updatePlayCounts(self):
|
||||||
#update all playcounts from MB3 to Kodi library
|
#update all playcounts from MB3 to Kodi library
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,9 @@ class PlayUtils():
|
||||||
|
|
||||||
# Works out if we are direct playing or not
|
# Works out if we are direct playing or not
|
||||||
def isDirectPlay(self, result):
|
def isDirectPlay(self, result):
|
||||||
|
return False
|
||||||
if (self.fileExists(result) or (result.get("LocationType") == "FileSystem" and self.isNetworkQualitySufficient(result) == True and self.isLocalPath(result) == False)):
|
if (self.fileExists(result) or (result.get("LocationType") == "FileSystem" and self.isNetworkQualitySufficient(result) == True and self.isLocalPath(result) == False)):
|
||||||
return True
|
return False
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,8 @@ import xbmcaddon
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
import Utils as utils
|
||||||
addondir = xbmc.translatePath(addon.getAddonInfo('profile'))
|
|
||||||
dataPath = os.path.join(addondir,"library")
|
|
||||||
movieLibrary = os.path.join(dataPath,'movies')
|
|
||||||
tvLibrary = os.path.join(dataPath,'tvshows')
|
|
||||||
musicvideoLibrary = os.path.join(dataPath,'musicvideos')
|
|
||||||
|
|
||||||
#sleepval is used to throttle the calls to the xbmc json API
|
#sleepval is used to throttle the calls to the xbmc json API
|
||||||
sleepVal = 15
|
sleepVal = 15
|
||||||
|
@ -44,11 +40,20 @@ class ReadKodiDB():
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
|
|
||||||
embyId = None
|
embyId = None
|
||||||
|
json_response = None
|
||||||
|
|
||||||
if type == "movie":
|
if type == "movie":
|
||||||
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieDetails", "params": { "movieid": %d, "properties" : ["imdbnumber","file"] }, "id": "libMovies"}' %kodiid)
|
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieDetails", "params": { "movieid": %d, "properties" : ["imdbnumber","file"] }, "id": "libMovies"}' %kodiid)
|
||||||
if type == "episode":
|
if type == "episode":
|
||||||
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": %d, "properties": ["file","uniqueid"]}, "id": 1}' %kodiid)
|
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": %d, "properties": ["file","uniqueid"]}, "id": 1}' %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]
|
||||||
|
|
||||||
if json_response != None:
|
if json_response != None:
|
||||||
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
||||||
|
@ -65,7 +70,7 @@ class ReadKodiDB():
|
||||||
if item['uniqueid'].has_key('unknown'):
|
if item['uniqueid'].has_key('unknown'):
|
||||||
embyId = item["uniqueid"]["unknown"]
|
embyId = item["uniqueid"]["unknown"]
|
||||||
|
|
||||||
return embyId
|
return embyId
|
||||||
|
|
||||||
def getKodiMovies(self,fullInfo = False):
|
def getKodiMovies(self,fullInfo = False):
|
||||||
#returns all movies in Kodi db
|
#returns all movies in Kodi db
|
||||||
|
@ -212,15 +217,25 @@ class ReadKodiDB():
|
||||||
def getKodiMusicVideo(self, id):
|
def getKodiMusicVideo(self, id):
|
||||||
#returns a single musicvideo from Kodi db selected on MB item ID
|
#returns a single musicvideo from Kodi db selected on MB item ID
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "filter": {"operator": "contains", "field": "path", "value": "' + id + '"}, "properties" : ["art", "thumbnail", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track","plot", "director", "playcount", "lastplayed", "tag", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libMusicVideos"}')
|
#get the mediabrowser ID from DB
|
||||||
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
connection = utils.KodiSQL()
|
||||||
musicvideo = None
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("SELECT idMVideo as musicvideoid FROM musicvideo WHERE c23 = ?",(id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
musicvideoid = None
|
||||||
|
if result != None:
|
||||||
|
musicvideoid = result[0]
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
if(jsonobject.has_key('result')):
|
if musicvideoid != None:
|
||||||
result = jsonobject['result']
|
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideosDetails", "params": { "musicvideoid": ' + musicvideoid + ', "properties" : ["art", "thumbnail", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track","plot", "director", "playcount", "lastplayed", "tag", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libMusicVideos"}')
|
||||||
if(result.has_key('musicvideos')):
|
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
||||||
musicvideos = result['musicvideos']
|
musicvideo = None
|
||||||
musicvideo = musicvideos[0]
|
|
||||||
|
if(jsonobject.has_key('result')):
|
||||||
|
result = jsonobject['result']
|
||||||
|
if(result.has_key('musicvideodetails')):
|
||||||
|
musicvideo = result['musicvideodetails']
|
||||||
|
|
||||||
return musicvideo
|
return musicvideo
|
||||||
|
|
||||||
|
@ -228,9 +243,9 @@ class ReadKodiDB():
|
||||||
#returns all musicvideos in Kodi db inserted by MB
|
#returns all musicvideos in Kodi db inserted by MB
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
if fullInfo:
|
if fullInfo:
|
||||||
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "filter": {"operator": "contains", "field": "path", "value": "plugin.video.emby"}, "properties" : ["art", "thumbnail", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track", "lastplayed", "plot", "director", "playcount", "tag", "file"] }, "id": "libMusicVideos"}')
|
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "properties" : ["art", "thumbnail", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track", "lastplayed", "plot", "director", "playcount", "tag", "file"] }, "id": "libMusicVideos"}')
|
||||||
else:
|
else:
|
||||||
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "filter": {"operator": "contains", "field": "path", "value": "plugin.video.emby"}, "properties" : ["resume", "playcount", "lastplayed", "file"] }, "id": "libMusicVideos"}')
|
json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "properties" : ["resume", "playcount", "lastplayed", "file", "track"] }, "id": "libMusicVideos"}')
|
||||||
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
jsonobject = json.loads(json_response.decode('utf-8','replace'))
|
||||||
musicvideos = None
|
musicvideos = None
|
||||||
if(jsonobject.has_key('result')):
|
if(jsonobject.has_key('result')):
|
||||||
|
@ -241,10 +256,16 @@ class ReadKodiDB():
|
||||||
kodiMusicVideoMap = None
|
kodiMusicVideoMap = None
|
||||||
if(musicvideos != None and len(musicvideos) > 0):
|
if(musicvideos != None and len(musicvideos) > 0):
|
||||||
kodiMusicVideoMap = {}
|
kodiMusicVideoMap = {}
|
||||||
|
connection = utils.KodiSQL()
|
||||||
|
cursor = connection.cursor()
|
||||||
for kodivideo in musicvideos:
|
for kodivideo in musicvideos:
|
||||||
key = kodivideo["file"][-37:-5] #extract the id from the file name
|
cursor.execute("SELECT c23 as MBid FROM musicvideo WHERE idMVideo = ?",(kodivideo["musicvideoid"],))
|
||||||
kodiMusicVideoMap[key] = kodivideo
|
result = cursor.fetchone()
|
||||||
|
if result != None:
|
||||||
|
key = result[0]
|
||||||
|
kodiMusicVideoMap[key] = kodivideo
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
return kodiMusicVideoMap
|
return kodiMusicVideoMap
|
||||||
|
|
||||||
def getKodiMusicVideoIds(self,returnMB3Ids = False):
|
def getKodiMusicVideoIds(self,returnMB3Ids = False):
|
||||||
|
|
|
@ -49,44 +49,6 @@ def convertEncoding(data):
|
||||||
except:
|
except:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def checkKodiSources():
|
|
||||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
|
||||||
addondir = xbmc.translatePath( addon.getAddonInfo('profile') )
|
|
||||||
dataPath = os.path.join(addondir,"library")
|
|
||||||
movieLibrary = os.path.join(dataPath,'movies')
|
|
||||||
tvLibrary = os.path.join(dataPath,'tvshows')
|
|
||||||
musicvideoLibrary = os.path.join(dataPath,'musicvideos')
|
|
||||||
|
|
||||||
# If no folder exists at the time, create it.
|
|
||||||
if xbmcvfs.exists(addondir) == False:
|
|
||||||
xbmcvfs.mkdir(addondir)
|
|
||||||
xbmc.log("Manually created %s" % addondir)
|
|
||||||
|
|
||||||
if not xbmcvfs.exists(dataPath + os.sep):
|
|
||||||
xbmcvfs.mkdir(dataPath)
|
|
||||||
if not xbmcvfs.exists(movieLibrary + os.sep):
|
|
||||||
xbmcvfs.mkdir(movieLibrary)
|
|
||||||
addKodiSource("mediabrowser_movies",movieLibrary,"movies")
|
|
||||||
if not xbmcvfs.exists(tvLibrary + os.sep):
|
|
||||||
xbmcvfs.mkdir(tvLibrary)
|
|
||||||
addKodiSource("mediabrowser_tvshows",tvLibrary,"tvshows")
|
|
||||||
if not xbmcvfs.exists(musicvideoLibrary + os.sep):
|
|
||||||
xbmcvfs.mkdir(musicvideoLibrary)
|
|
||||||
addKodiSource("mediabrowser_musicvideos",musicvideoLibrary,"musicvideos")
|
|
||||||
|
|
||||||
rebootRequired = KodiAdvancedSettingsCheck()
|
|
||||||
|
|
||||||
if rebootRequired:
|
|
||||||
ret = xbmcgui.Dialog().yesno(heading="Emby Sync service", line1="A restart of Kodi is needed to apply changes.", line2="Synchronisation will not start before the restart.", line3="Do you want to restart now?")
|
|
||||||
if ret:
|
|
||||||
xbmc.executebuiltin("RestartApp")
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def KodiSQL():
|
def KodiSQL():
|
||||||
if xbmc.getInfoLabel("System.BuildVersion").startswith("13"):
|
if xbmc.getInfoLabel("System.BuildVersion").startswith("13"):
|
||||||
#gotham
|
#gotham
|
||||||
|
@ -104,80 +66,6 @@ def KodiSQL():
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
|
|
||||||
def addKodiSource(name, path, type):
|
|
||||||
#add new source to database, common way is to add it directly to the Kodi DB. Fallback to adding it to the sources.xml
|
|
||||||
#return boolean wether a manual reboot is required.
|
|
||||||
#todo: Do feature request with Kodi team to get support for adding a source by the json API
|
|
||||||
|
|
||||||
error = False
|
|
||||||
try:
|
|
||||||
connection = KodiSQL()
|
|
||||||
cursor = connection.cursor( )
|
|
||||||
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, strHash, scanRecursive) values(?, ?, ?, ?, ?, ?)"
|
|
||||||
cursor.execute(pathsql, (pathId,path + os.sep,type,"metadata.local",None,2147483647))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
except:
|
|
||||||
error = True
|
|
||||||
|
|
||||||
# add it to sources.xml
|
|
||||||
sourcesFile = xbmc.translatePath( "special://profile/sources.xml" )
|
|
||||||
|
|
||||||
# add an empty sources file to work with
|
|
||||||
if xbmcvfs.exists(sourcesFile) == False:
|
|
||||||
sources = Element("sources")
|
|
||||||
video = SubElement(sources, "video")
|
|
||||||
ET.ElementTree(sources).write(sourcesFile)
|
|
||||||
|
|
||||||
if xbmcvfs.exists(sourcesFile):
|
|
||||||
tree = ET.ElementTree(file=sourcesFile)
|
|
||||||
root = tree.getroot()
|
|
||||||
videosources = root.find("video")
|
|
||||||
#remove any existing entries for this path
|
|
||||||
allsources = videosources.findall("source")
|
|
||||||
if allsources != None:
|
|
||||||
for source in allsources:
|
|
||||||
if source.find("name").text == name:
|
|
||||||
videosources.remove(source)
|
|
||||||
# add the new source
|
|
||||||
source = SubElement(videosources,'source')
|
|
||||||
SubElement(source, "name").text = name
|
|
||||||
SubElement(source, "path").text = path
|
|
||||||
tree.write(sourcesFile)
|
|
||||||
|
|
||||||
def KodiAdvancedSettingsCheck():
|
|
||||||
#setting that kodi should import watched state and resume points from the nfo files
|
|
||||||
settingsFile = xbmc.translatePath( "special://profile/advancedsettings.xml" )
|
|
||||||
# add an empty sources file to work with
|
|
||||||
if xbmcvfs.exists(settingsFile) == False:
|
|
||||||
sources = Element("advancedsettings")
|
|
||||||
video = SubElement(sources, "videolibrary")
|
|
||||||
ET.ElementTree(sources).write(settingsFile)
|
|
||||||
|
|
||||||
writeNeeded = False
|
|
||||||
if xbmcvfs.exists(settingsFile):
|
|
||||||
tree = ET.ElementTree(file=settingsFile)
|
|
||||||
root = tree.getroot()
|
|
||||||
video = root.find("videolibrary")
|
|
||||||
if video == None:
|
|
||||||
video = SubElement(root, "videolibrary")
|
|
||||||
# add the settings
|
|
||||||
if video.find("importwatchedstate") == None:
|
|
||||||
writeNeeded = True
|
|
||||||
SubElement(video, "importwatchedstate").text = "true"
|
|
||||||
if video.find("importresumepoint") == None:
|
|
||||||
writeNeeded = True
|
|
||||||
SubElement(video, "importresumepoint").text = "true"
|
|
||||||
|
|
||||||
if writeNeeded:
|
|
||||||
tree.write(settingsFile)
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def checkAuthentication():
|
def checkAuthentication():
|
||||||
#check authentication
|
#check authentication
|
||||||
if addonSettings.getSetting('username') != "" and addonSettings.getSetting('ipaddress') != "":
|
if addonSettings.getSetting('username') != "" and addonSettings.getSetting('ipaddress') != "":
|
||||||
|
|
|
@ -20,13 +20,6 @@ from ReadEmbyDB import ReadEmbyDB
|
||||||
from API import API
|
from API import API
|
||||||
import Utils as utils
|
import Utils as utils
|
||||||
|
|
||||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
|
||||||
addondir = xbmc.translatePath(addon.getAddonInfo('profile'))
|
|
||||||
dataPath = os.path.join(addondir,"library")
|
|
||||||
movieLibrary = os.path.join(dataPath,'movies')
|
|
||||||
tvLibrary = os.path.join(dataPath,'tvshows')
|
|
||||||
musicvideoLibrary = os.path.join(dataPath,'musicvideos')
|
|
||||||
|
|
||||||
sleepVal = 20
|
sleepVal = 20
|
||||||
|
|
||||||
class WriteKodiDB():
|
class WriteKodiDB():
|
||||||
|
@ -76,15 +69,11 @@ class WriteKodiDB():
|
||||||
|
|
||||||
#set Filename
|
#set Filename
|
||||||
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
docleanup = self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie")
|
self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie", MBitem["Id"])
|
||||||
#if the path has been set directly in the DB, cleanup the locally created files to import the media-item into the Kodi DB to prevent Kodi from scanning it again.
|
|
||||||
if docleanup:
|
|
||||||
itemPath = os.path.join(movieLibrary,MBitem["Id"])
|
|
||||||
utils.removeDirectory(os.path.join(movieLibrary,MBitem["Id"] + os.sep))
|
|
||||||
|
|
||||||
#update common properties
|
#update common properties
|
||||||
duration = (int(timeInfo.get('Duration'))*60)
|
if KodiItem["runtime"] == 0:
|
||||||
self.getPropertyParam_Batched(KodiItem, "runtime", duration, params)
|
self.getPropertyParam_Batched(KodiItem, "runtime", (int(timeInfo.get('Duration'))*60), params)
|
||||||
self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
|
self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
|
||||||
self.getPropertyParam_Batched(KodiItem, "mpaa", MBitem.get("OfficialRating"), params)
|
self.getPropertyParam_Batched(KodiItem, "mpaa", MBitem.get("OfficialRating"), params)
|
||||||
self.getPropertyParam_Batched(KodiItem, "lastplayed", userData.get("LastPlayedDate"), params)
|
self.getPropertyParam_Batched(KodiItem, "lastplayed", userData.get("LastPlayedDate"), params)
|
||||||
|
@ -126,7 +115,7 @@ class WriteKodiDB():
|
||||||
if(jsonData != ""):
|
if(jsonData != ""):
|
||||||
trailerItem = json.loads(jsonData)
|
trailerItem = json.loads(jsonData)
|
||||||
if trailerItem[0].get("LocationType") == "FileSystem":
|
if trailerItem[0].get("LocationType") == "FileSystem":
|
||||||
trailerUrl = "plugin://plugin.video.emby/?id=" + trailerItem[0].get("Id") + '&mode=play'
|
trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0].get("Id"), trailerItem[0])
|
||||||
self.getPropertyParam_Batched(KodiItem, "trailer", trailerUrl, params)
|
self.getPropertyParam_Batched(KodiItem, "trailer", trailerUrl, params)
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,14 +140,6 @@ class WriteKodiDB():
|
||||||
#add actors
|
#add actors
|
||||||
changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"), "movie")
|
changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"), "movie")
|
||||||
|
|
||||||
#add theme music
|
|
||||||
if addon.getSetting("syncThemeMusic") == "true":
|
|
||||||
CreateFiles().copyThemeMusic(MBitem)
|
|
||||||
|
|
||||||
#add extra fanart
|
|
||||||
if addon.getSetting("syncExtraFanart") == "true":
|
|
||||||
CreateFiles().copyExtraFanart(MBitem)
|
|
||||||
|
|
||||||
if(changes):
|
if(changes):
|
||||||
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
|
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
|
||||||
|
|
||||||
|
@ -186,8 +167,8 @@ class WriteKodiDB():
|
||||||
self.getArtworkParam_Batched(KodiItem, MBitem, params)
|
self.getArtworkParam_Batched(KodiItem, MBitem, params)
|
||||||
|
|
||||||
#update common properties
|
#update common properties
|
||||||
duration = (int(timeInfo.get('Duration'))*60)
|
if KodiItem["runtime"] == None:
|
||||||
self.getPropertyParam_Batched(KodiItem, "runtime", duration, params)
|
self.getPropertyParam_Batched(KodiItem, "runtime", (int(timeInfo.get('Duration'))*60), params)
|
||||||
self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
|
self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
|
||||||
self.getPropertyParamArray_Batched(KodiItem, "director", people.get("Director"), params)
|
self.getPropertyParamArray_Batched(KodiItem, "director", people.get("Director"), params)
|
||||||
self.getPropertyParamArray_Batched(KodiItem, "genre", MBitem.get("Genres"), params)
|
self.getPropertyParamArray_Batched(KodiItem, "genre", MBitem.get("Genres"), params)
|
||||||
|
@ -218,9 +199,6 @@ class WriteKodiDB():
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
result = xbmc.executeJSONRPC(jsoncommand.encode("utf-8"))
|
result = xbmc.executeJSONRPC(jsoncommand.encode("utf-8"))
|
||||||
|
|
||||||
CreateFiles().createSTRM(MBitem)
|
|
||||||
CreateFiles().createNFO(MBitem)
|
|
||||||
|
|
||||||
if(changes):
|
if(changes):
|
||||||
utils.logMsg("Updated musicvideo to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
|
utils.logMsg("Updated musicvideo to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
|
||||||
|
|
||||||
|
@ -248,8 +226,6 @@ class WriteKodiDB():
|
||||||
changes |= self.updateArtWork(KodiItem,MBitem)
|
changes |= self.updateArtWork(KodiItem,MBitem)
|
||||||
|
|
||||||
#update common properties
|
#update common properties
|
||||||
duration = (int(timeInfo.get('Duration'))*60)
|
|
||||||
changes |= self.updateProperty(KodiItem,"runtime",duration,"movie")
|
|
||||||
changes |= self.updateProperty(KodiItem,"year",MBitem.get("ProductionYear"),"movie")
|
changes |= self.updateProperty(KodiItem,"year",MBitem.get("ProductionYear"),"movie")
|
||||||
changes |= self.updateProperty(KodiItem,"mpaa",MBitem.get("OfficialRating"),"movie")
|
changes |= self.updateProperty(KodiItem,"mpaa",MBitem.get("OfficialRating"),"movie")
|
||||||
changes |= self.updateProperty(KodiItem,"lastplayed",MBitem.get("LastPlayedDate"),"movie")
|
changes |= self.updateProperty(KodiItem,"lastplayed",MBitem.get("LastPlayedDate"),"movie")
|
||||||
|
@ -289,7 +265,7 @@ class WriteKodiDB():
|
||||||
jsonData = downloadUtils.downloadUrl(itemTrailerUrl, suppress=False, popup=0 )
|
jsonData = downloadUtils.downloadUrl(itemTrailerUrl, suppress=False, popup=0 )
|
||||||
if(jsonData != ""):
|
if(jsonData != ""):
|
||||||
trailerItem = json.loads(jsonData)
|
trailerItem = json.loads(jsonData)
|
||||||
trailerUrl = "plugin://plugin.video.emby/?id=" + trailerItem[0].get("Id") + '&mode=play'
|
trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0].get("Id"), MBitem)
|
||||||
changes |= self.updateProperty(KodiItem,"trailer",trailerUrl,"movie")
|
changes |= self.updateProperty(KodiItem,"trailer",trailerUrl,"movie")
|
||||||
|
|
||||||
#add actors
|
#add actors
|
||||||
|
@ -299,15 +275,6 @@ class WriteKodiDB():
|
||||||
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie")
|
self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie")
|
||||||
|
|
||||||
|
|
||||||
#add theme music
|
|
||||||
if addon.getSetting("syncThemeMusic") == "true":
|
|
||||||
CreateFiles().copyThemeMusic(MBitem)
|
|
||||||
|
|
||||||
#add extra fanart
|
|
||||||
if addon.getSetting("syncExtraFanart") == "true":
|
|
||||||
CreateFiles().copyExtraFanart(MBitem)
|
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
|
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
|
||||||
|
@ -334,12 +301,7 @@ class WriteKodiDB():
|
||||||
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
#make sure that the path always ends with a slash
|
#make sure that the path always ends with a slash
|
||||||
playurl = playurl + "/"
|
playurl = playurl + "/"
|
||||||
docleanup = self.setKodiFilename(KodiItem["tvshowid"], KodiItem["file"], playurl, "tvshow")
|
self.setKodiFilename(KodiItem["tvshowid"], KodiItem["file"], playurl, "tvshow", MBitem["Id"])
|
||||||
|
|
||||||
#if the path has been set directly in the DB, cleanup the locally created nfo file to import the tvshow into the Kodi DB to prevent Kodi from scanning it again.
|
|
||||||
nfoPath = os.path.join(tvLibrary,MBitem["Id"],"tvshow.nfo")
|
|
||||||
if xbmcvfs.exists(nfoPath):
|
|
||||||
xbmcvfs.delete(nfoPath)
|
|
||||||
|
|
||||||
#update/check all artwork
|
#update/check all artwork
|
||||||
changes |= self.updateArtWork(KodiItem,MBitem)
|
changes |= self.updateArtWork(KodiItem,MBitem)
|
||||||
|
@ -375,18 +337,8 @@ class WriteKodiDB():
|
||||||
#add actors
|
#add actors
|
||||||
changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"tvshow")
|
changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"tvshow")
|
||||||
|
|
||||||
#update season artwork
|
#update season details
|
||||||
self.updateSeasonArtwork(MBitem, KodiItem)
|
self.updateSeasons(MBitem, KodiItem)
|
||||||
|
|
||||||
#CreateFiles().createNFO(MBitem)
|
|
||||||
|
|
||||||
#add theme music
|
|
||||||
if addon.getSetting("syncThemeMusic") == "true":
|
|
||||||
CreateFiles().copyThemeMusic(MBitem)
|
|
||||||
|
|
||||||
#add extra fanart
|
|
||||||
if addon.getSetting("syncExtraFanart") == "true":
|
|
||||||
CreateFiles().copyExtraFanart(MBitem)
|
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
|
utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
@ -416,22 +368,13 @@ class WriteKodiDB():
|
||||||
#update/check all artwork
|
#update/check all artwork
|
||||||
changes |= self.updateArtWork(KodiItem,MBitem)
|
changes |= self.updateArtWork(KodiItem,MBitem)
|
||||||
|
|
||||||
#set Filename (also submit strmfilepath to rename that if path has changed to original location)
|
#set Filename (will update the filename in db if changed)
|
||||||
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
docleanup = self.setKodiFilename(KodiItem["episodeid"], KodiItem["file"], playurl, "episode")
|
docleanup = self.setKodiFilename(KodiItem["episodeid"], KodiItem["file"], playurl, "episode", MBitem["Id"])
|
||||||
|
|
||||||
#if the path has been set directly in the DB, cleanup the locally created files to import the media-item into the Kodi DB to prevent Kodi from scanning it again.
|
|
||||||
if docleanup:
|
|
||||||
path = os.path.join(tvLibrary,MBitem["SeriesId"] + os.sep)
|
|
||||||
if xbmcvfs.exists(path):
|
|
||||||
allDirs, allFiles = xbmcvfs.listdir(path)
|
|
||||||
for file in allFiles:
|
|
||||||
if MBitem["Id"] in file:
|
|
||||||
xbmcvfs.delete(os.path.join(path,file))
|
|
||||||
|
|
||||||
#update common properties
|
#update common properties
|
||||||
duration = (int(timeInfo.get('Duration'))*60)
|
if KodiItem["runtime"] == 0:
|
||||||
changes |= self.updateProperty(KodiItem,"runtime",duration,"episode")
|
changes |= self.updateProperty(KodiItem,"runtime",(int(timeInfo.get('Duration'))*60),"episode")
|
||||||
changes |= self.updateProperty(KodiItem,"lastplayed",userData.get("LastPlayedDate"),"episode")
|
changes |= self.updateProperty(KodiItem,"lastplayed",userData.get("LastPlayedDate"),"episode")
|
||||||
|
|
||||||
if MBitem.get("PremiereDate") != None:
|
if MBitem.get("PremiereDate") != None:
|
||||||
|
@ -696,56 +639,306 @@ class WriteKodiDB():
|
||||||
|
|
||||||
return pendingChanges
|
return pendingChanges
|
||||||
|
|
||||||
def addMovieToKodiLibrary( self, item ):
|
def addMovieToKodiLibrary( self, MBitem ):
|
||||||
itemPath = os.path.join(movieLibrary,item["Id"])
|
#adds a movie to Kodi by directly inserting it to the DB while there is no addmovie available on the json API
|
||||||
strmFile = os.path.join(itemPath,item["Id"] + ".strm")
|
#TODO: PR at Kodi team for a addMovie endpoint on their API
|
||||||
|
|
||||||
changes = False
|
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
|
port = addon.getSetting('port')
|
||||||
|
host = addon.getSetting('ipaddress')
|
||||||
|
server = host + ":" + port
|
||||||
|
downloadUtils = DownloadUtils()
|
||||||
|
userid = downloadUtils.getUserId()
|
||||||
|
|
||||||
#create path if not exists
|
timeInfo = API().getTimeInfo(MBitem)
|
||||||
if not xbmcvfs.exists(itemPath + os.sep):
|
userData=API().getUserData(MBitem)
|
||||||
xbmcvfs.mkdir(itemPath)
|
people = API().getPeople(MBitem)
|
||||||
|
genre = API().getGenre(MBitem)
|
||||||
|
studios = API().getStudios(MBitem)
|
||||||
|
mediaStreams=API().getMediaStreams(MBitem)
|
||||||
|
|
||||||
#create nfo file
|
thumbPath = API().getArtwork(MBitem, "Primary")
|
||||||
changes = CreateFiles().createNFO(item)
|
|
||||||
|
|
||||||
# create strm file
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
changes |= CreateFiles().createSTRM(item)
|
playurl = utils.convertEncoding(playurl)
|
||||||
|
|
||||||
if changes:
|
if MBitem.get("DateCreated") != None:
|
||||||
utils.logMsg("MB3 Sync","Added movie to Kodi Library",item["Id"] + " - " + item["Name"])
|
dateadded = MBitem["DateCreated"].replace("T"," ")
|
||||||
|
dateadded = dateadded.replace(".0000000Z","")
|
||||||
|
else:
|
||||||
|
dateadded = None
|
||||||
|
|
||||||
def addMusicVideoToKodiLibrary( self, item ):
|
connection = utils.KodiSQL()
|
||||||
itemPath = os.path.join(musicvideoLibrary,item["Id"])
|
cursor = connection.cursor()
|
||||||
strmFile = os.path.join(itemPath,item["Id"] + ".strm")
|
|
||||||
|
|
||||||
changes = False
|
# 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 path if not exists
|
#create the path
|
||||||
if not xbmcvfs.exists(itemPath + os.sep):
|
cursor.execute("select coalesce(max(idPath),0) as pathid from path")
|
||||||
xbmcvfs.mkdir(itemPath)
|
pathid = cursor.fetchone()[0]
|
||||||
|
pathid = pathid + 1
|
||||||
|
pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (pathid,path,"movies","metadata.local",1))
|
||||||
|
|
||||||
#create nfo file
|
playcount = None
|
||||||
changes = CreateFiles().createNFO(item)
|
if userData.get("PlayCount") == "1":
|
||||||
|
playcount = 1
|
||||||
|
|
||||||
# create strm file
|
#create the file if not exists
|
||||||
changes |= CreateFiles().createSTRM(item)
|
cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ?",(filename,))
|
||||||
|
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
|
||||||
|
pathsql="insert into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (fileid,pathid,filename,playcount,userData.get("LastPlayedDate"),dateadded))
|
||||||
|
|
||||||
if changes:
|
runtime = int(timeInfo.get('Duration'))*60
|
||||||
utils.logMsg("MB3 Sync","Added musicvideo to Kodi Library",item["Id"] + " - " + item["Name"])
|
plot = utils.convertEncoding(API().getOverview(MBitem))
|
||||||
|
thumb = "<thumb>" + API().getArtwork(MBitem, "Primary") + "</thumb>"
|
||||||
|
fanart = "<fanart>" + API().getArtwork(MBitem, "Backdrop") + "</fanart>"
|
||||||
|
title = utils.convertEncoding(MBitem["Name"])
|
||||||
|
sorttitle = utils.convertEncoding(MBitem["SortName"])
|
||||||
|
year = MBitem.get("ProductionYear")
|
||||||
|
if MBitem.get("CriticRating") != None:
|
||||||
|
rating = int(MBitem.get("CriticRating"))/10
|
||||||
|
else:
|
||||||
|
rating = None
|
||||||
|
if MBitem.get("ShortOverview") != None:
|
||||||
|
shortplot = utils.convertEncoding(MBitem.get("ShortOverview"))
|
||||||
|
else:
|
||||||
|
shortplot = None
|
||||||
|
|
||||||
def addEpisodeToKodiLibrary(self, item):
|
trailerUrl = None
|
||||||
|
if MBitem.get("LocalTrailerCount") != None and MBitem.get("LocalTrailerCount") > 0:
|
||||||
|
itemTrailerUrl = "http://" + server + "/mediabrowser/Users/" + userid + "/Items/" + MBitem.get("Id") + "/LocalTrailers?format=json"
|
||||||
|
jsonData = downloadUtils.downloadUrl(itemTrailerUrl, suppress=False, popup=0 )
|
||||||
|
if(jsonData != ""):
|
||||||
|
trailerItem = json.loads(jsonData)
|
||||||
|
if trailerItem[0].get("LocationType") == "FileSystem":
|
||||||
|
trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0].get("Id"), trailerItem[0])
|
||||||
|
|
||||||
changes = False
|
#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, c04, c07, c08, c09, c10, c11, c16, c19, c20) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (movieid, fileid, title, plot, shortplot, rating, year, thumb, MBitem["Id"], sorttitle, runtime, title, trailerUrl, fanart))
|
||||||
|
|
||||||
#create nfo file
|
try:
|
||||||
changes = CreateFiles().createNFO(item)
|
connection.commit()
|
||||||
|
utils.logMsg("MB3 Sync","Added movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
except:
|
||||||
|
utils.logMsg("MB3 Sync","Error adding movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
actionPerformed = False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
# create strm file
|
def addMusicVideoToKodiLibrary( self, MBitem ):
|
||||||
changes |= CreateFiles().createSTRM(item)
|
|
||||||
|
|
||||||
if changes:
|
#adds a musicvideo to Kodi by directly inserting it to the DB while there is no addMusicVideo available on the json API
|
||||||
utils.logMsg("MB3 Sync","Added episode to Kodi Library",item["Id"] + " - " + item["Name"])
|
#TODO: PR at Kodi team for a addMusicVideo endpoint on their API
|
||||||
|
|
||||||
|
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
|
port = addon.getSetting('port')
|
||||||
|
host = addon.getSetting('ipaddress')
|
||||||
|
server = host + ":" + port
|
||||||
|
downloadUtils = DownloadUtils()
|
||||||
|
userid = downloadUtils.getUserId()
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
|
playurl = utils.convertEncoding(playurl)
|
||||||
|
|
||||||
|
if MBitem.get("DateCreated") != None:
|
||||||
|
dateadded = MBitem["DateCreated"].replace("T"," ")
|
||||||
|
dateadded = dateadded.replace(".0000000Z","")
|
||||||
|
else:
|
||||||
|
dateadded = None
|
||||||
|
|
||||||
|
connection = utils.KodiSQL()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# 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 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,"musicvideos","metadata.local",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 = ?",(filename,))
|
||||||
|
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
|
||||||
|
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))
|
||||||
|
thumb = "<thumb>" + API().getArtwork(MBitem, "Primary") + "</thumb>"
|
||||||
|
title = utils.convertEncoding(MBitem["Name"])
|
||||||
|
|
||||||
|
#create the musicvideo
|
||||||
|
cursor.execute("select coalesce(max(idMVideo),0) as musicvideoid from musicvideo")
|
||||||
|
musicvideoid = cursor.fetchone()[0]
|
||||||
|
musicvideoid = musicvideoid + 1
|
||||||
|
pathsql="insert into musicvideo(idMVideo, idFile, c00, c01, c04, c08, c23) values(?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (musicvideoid, fileid, title, thumb, runtime, plot, MBitem["Id"]))
|
||||||
|
|
||||||
|
try:
|
||||||
|
connection.commit()
|
||||||
|
utils.logMsg("MB3 Sync","Added musicvideo to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
except:
|
||||||
|
utils.logMsg("MB3 Sync","Error adding musicvideo to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
actionPerformed = False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
def addEpisodeToKodiLibrary(self, MBitem):
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
|
port = addon.getSetting('port')
|
||||||
|
host = addon.getSetting('ipaddress')
|
||||||
|
server = host + ":" + port
|
||||||
|
downloadUtils = DownloadUtils()
|
||||||
|
userid = downloadUtils.getUserId()
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
connection = utils.KodiSQL()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# 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 = ?",(filename,))
|
||||||
|
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"],))
|
||||||
|
showid = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
season = 0
|
||||||
|
if MBitem.get("ParentIndexNumber") != None:
|
||||||
|
season = int(MBitem.get("ParentIndexNumber"))
|
||||||
|
|
||||||
|
episode = 0
|
||||||
|
if MBitem.get("IndexNumber") != None:
|
||||||
|
episode = int(MBitem.get("IndexNumber"))
|
||||||
|
|
||||||
|
runtime = int(timeInfo.get('Duration'))*60
|
||||||
|
plot = utils.convertEncoding(API().getOverview(MBitem))
|
||||||
|
thumb = "<thumb>" + API().getArtwork(MBitem, "Primary") + "</thumb>"
|
||||||
|
title = utils.convertEncoding(MBitem["Name"])
|
||||||
|
if MBitem.get("CriticRating") != None:
|
||||||
|
rating = int(MBitem.get("CriticRating"))/10
|
||||||
|
else:
|
||||||
|
rating = 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, c06, c09, c20, c12, c13, c14, idShow) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (episodeid, fileid, title, plot, rating, thumb, runtime, MBitem["Id"], season, episode, title, showid))
|
||||||
|
|
||||||
|
try:
|
||||||
|
connection.commit()
|
||||||
|
utils.logMsg("MB3 Sync","Added TV Show to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
except:
|
||||||
|
utils.logMsg("MB3 Sync","Error adding tvshow to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
actionPerformed = False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
def deleteMovieFromKodiLibrary(self, id ):
|
def deleteMovieFromKodiLibrary(self, id ):
|
||||||
kodiItem = ReadKodiDB().getKodiMovie(id)
|
kodiItem = ReadKodiDB().getKodiMovie(id)
|
||||||
|
@ -753,24 +946,12 @@ class WriteKodiDB():
|
||||||
if kodiItem != None:
|
if kodiItem != None:
|
||||||
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMovie", "params": { "movieid": %i}, "id": 1 }' %(kodiItem["movieid"]))
|
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMovie", "params": { "movieid": %i}, "id": 1 }' %(kodiItem["movieid"]))
|
||||||
|
|
||||||
path = os.path.join(movieLibrary,id + os.sep)
|
|
||||||
utils.removeDirectory(path)
|
|
||||||
|
|
||||||
|
|
||||||
def deleteMusicVideoFromKodiLibrary(self, id ):
|
def deleteMusicVideoFromKodiLibrary(self, id ):
|
||||||
utils.logMsg("deleting musicvideo from Kodi library",id)
|
utils.logMsg("deleting musicvideo from Kodi library",id)
|
||||||
kodiItem = ReadKodiDB().getKodiMusicVideo(id)
|
kodiItem = ReadKodiDB().getKodiMusicVideo(id)
|
||||||
if kodiItem != None:
|
if kodiItem != None:
|
||||||
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMusicVideo", "params": { "musicvideoid": %i}, "id": 1 }' %(kodiItem["musicvideoid"]))
|
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMusicVideo", "params": { "musicvideoid": %i}, "id": 1 }' %(kodiItem["musicvideoid"]))
|
||||||
|
|
||||||
path = os.path.join(musicvideoLibrary,id)
|
|
||||||
allDirs, allFiles = xbmcvfs.listdir(path)
|
|
||||||
for dir in allDirs:
|
|
||||||
xbmcvfs.rmdir(os.path.join(path,dir))
|
|
||||||
for file in allFiles:
|
|
||||||
xbmcvfs.delete(os.path.join(path,file))
|
|
||||||
xbmcvfs.rmdir(path)
|
|
||||||
|
|
||||||
def deleteEpisodeFromKodiLibrary(self, episodeid, tvshowid ):
|
def deleteEpisodeFromKodiLibrary(self, episodeid, tvshowid ):
|
||||||
utils.logMsg("deleting episode from Kodi library",episodeid)
|
utils.logMsg("deleting episode from Kodi library",episodeid)
|
||||||
episode = ReadKodiDB().getKodiEpisodeByMbItem(episodeid, tvshowid)
|
episode = ReadKodiDB().getKodiEpisodeByMbItem(episodeid, tvshowid)
|
||||||
|
@ -779,32 +960,82 @@ class WriteKodiDB():
|
||||||
WINDOW.setProperty("suspendDeletes", "True")
|
WINDOW.setProperty("suspendDeletes", "True")
|
||||||
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(episode["episodeid"]))
|
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(episode["episodeid"]))
|
||||||
|
|
||||||
itemPath = os.path.join(tvLibrary,tvshowid)
|
|
||||||
allDirs, allFiles = xbmcvfs.listdir(itemPath)
|
|
||||||
for file in allFiles:
|
|
||||||
if episodeid in file:
|
|
||||||
xbmcvfs.delete(file)
|
|
||||||
|
|
||||||
while WINDOW.getProperty("suspendDeletes") == "True":
|
while WINDOW.getProperty("suspendDeletes") == "True":
|
||||||
xbmc.sleep(100)
|
xbmc.sleep(100)
|
||||||
utils.logMsg("episode deleted succesfully!",episodeid)
|
utils.logMsg("episode deleted succesfully!",episodeid)
|
||||||
else:
|
else:
|
||||||
utils.logMsg("episode not found in kodi DB",episodeid)
|
utils.logMsg("episode not found in kodi DB",episodeid)
|
||||||
|
|
||||||
def addTVShowToKodiLibrary( self, item ):
|
def addTVShowToKodiLibrary( self, MBitem ):
|
||||||
itemPath = os.path.join(tvLibrary,item["Id"])
|
#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
|
||||||
|
|
||||||
changes = False
|
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
|
port = addon.getSetting('port')
|
||||||
|
host = addon.getSetting('ipaddress')
|
||||||
|
server = host + ":" + port
|
||||||
|
downloadUtils = DownloadUtils()
|
||||||
|
userid = downloadUtils.getUserId()
|
||||||
|
|
||||||
#create path if not exists
|
timeInfo = API().getTimeInfo(MBitem)
|
||||||
if not xbmcvfs.exists(itemPath + os.sep):
|
userData=API().getUserData(MBitem)
|
||||||
xbmcvfs.mkdir(itemPath)
|
people = API().getPeople(MBitem)
|
||||||
|
genre = API().getGenre(MBitem)
|
||||||
|
studios = API().getStudios(MBitem)
|
||||||
|
mediaStreams=API().getMediaStreams(MBitem)
|
||||||
|
|
||||||
#create nfo file
|
thumbPath = API().getArtwork(MBitem, "Primary")
|
||||||
changes = CreateFiles().createNFO(item)
|
|
||||||
|
|
||||||
if changes:
|
playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
|
||||||
utils.logMsg("Added TV Show to Kodi Library ",item["Id"] + " - " + item["Name"])
|
#make sure that the path always ends with a slash
|
||||||
|
path = playurl + "/"
|
||||||
|
|
||||||
|
if MBitem.get("DateCreated") != None:
|
||||||
|
dateadded = MBitem["DateCreated"].replace("T"," ")
|
||||||
|
dateadded = dateadded.replace(".0000000Z","")
|
||||||
|
else:
|
||||||
|
dateadded = None
|
||||||
|
|
||||||
|
connection = utils.KodiSQL()
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
#create the 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))
|
||||||
|
|
||||||
|
runtime = int(timeInfo.get('Duration'))*60
|
||||||
|
plot = utils.convertEncoding(API().getOverview(MBitem))
|
||||||
|
thumb = "<thumb>" + API().getArtwork(MBitem, "Primary") + "</thumb>"
|
||||||
|
fanart = "<fanart>" + API().getArtwork(MBitem, "Backdrop") + "</fanart>"
|
||||||
|
title = utils.convertEncoding(MBitem["Name"])
|
||||||
|
sorttitle = utils.convertEncoding(MBitem["SortName"])
|
||||||
|
if MBitem.get("CriticRating") != None:
|
||||||
|
rating = int(MBitem.get("CriticRating"))/10
|
||||||
|
else:
|
||||||
|
rating = None
|
||||||
|
|
||||||
|
#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, c06, c09, c11, c12, c15) values(?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
cursor.execute(pathsql, (showid, title, plot, rating, thumb, title, fanart, MBitem["Id"], sorttitle))
|
||||||
|
|
||||||
|
#link the path
|
||||||
|
pathsql="insert into tvshowlinkpath(idShow,idPath) values(?, ?)"
|
||||||
|
cursor.execute(pathsql, (showid,pathid))
|
||||||
|
|
||||||
|
try:
|
||||||
|
connection.commit()
|
||||||
|
utils.logMsg("MB3 Sync","Added TV Show to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
except:
|
||||||
|
utils.logMsg("MB3 Sync","Error adding tvshow to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
|
||||||
|
actionPerformed = False
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
def deleteTVShowFromKodiLibrary(self, id ):
|
def deleteTVShowFromKodiLibrary(self, id ):
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
|
@ -814,34 +1045,33 @@ class WriteKodiDB():
|
||||||
if kodiItem != None:
|
if kodiItem != None:
|
||||||
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveTVShow", "params": { "tvshowid": %i}, "id": 1 }' %(kodiItem["tvshowid"]))
|
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveTVShow", "params": { "tvshowid": %i}, "id": 1 }' %(kodiItem["tvshowid"]))
|
||||||
|
|
||||||
path = os.path.join(tvLibrary,id + os.sep)
|
def updateSeasons(self,MBitem, KodiItem):
|
||||||
utils.removeDirectory(path)
|
#use sqlite to set the season details because no method in API available for this
|
||||||
|
|
||||||
|
|
||||||
def updateSeasonArtwork(self,MBitem, KodiItem):
|
|
||||||
#use sqlite to set the season artwork because no method in API available for this
|
|
||||||
#season poster and banner are set by the nfo. landscape image is filled by this method
|
|
||||||
#if wanted this feature can be extended to also update the other artwork
|
|
||||||
tvshowid = KodiItem["tvshowid"]
|
tvshowid = KodiItem["tvshowid"]
|
||||||
|
|
||||||
connection = utils.KodiSQL()
|
connection = utils.KodiSQL()
|
||||||
cursor = connection.cursor( )
|
cursor = connection.cursor()
|
||||||
|
|
||||||
seasonData = ReadEmbyDB().getTVShowSeasons(MBitem["Id"])
|
seasonData = ReadEmbyDB().getTVShowSeasons(MBitem["Id"])
|
||||||
if seasonData != None:
|
if seasonData != None:
|
||||||
for season in seasonData:
|
for season in seasonData:
|
||||||
if season.has_key("IndexNumber"):
|
if season.has_key("IndexNumber"):
|
||||||
MB3landscape = API().getArtwork(season, "Thumb")
|
cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(tvshowid,season["IndexNumber"]))
|
||||||
if MB3landscape != "":
|
result = cursor.fetchone()
|
||||||
cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(tvshowid,season["IndexNumber"]))
|
if result == None:
|
||||||
result = cursor.fetchone()
|
#create the season
|
||||||
if result != None:
|
cursor.execute("select coalesce(max(idSeason),0) as seasonid from seasons")
|
||||||
seasonid = result[0]
|
seasonid = cursor.fetchone()[0]
|
||||||
cursor.execute("SELECT art_id as art_id FROM art WHERE media_id = ? and media_type = ? and type = ?",(seasonid,"season","landscape"))
|
seasonid = seasonid + 1
|
||||||
result = cursor.fetchone()
|
cursor.execute("INSERT into seasons(idSeason, idShow, season) values(?, ?, ?)", (seasonid, tvshowid, season["IndexNumber"]))
|
||||||
if result == None:
|
|
||||||
sql="INSERT into art(media_id, media_type, type, url) values(?, ?, ?, ?)"
|
#insert artwork
|
||||||
cursor.execute(sql, (seasonid,"season","landscape",MB3landscape))
|
if API().getArtwork(season, "Thumb") != "":
|
||||||
|
cursor.execute("INSERT into art(media_id, media_type, type, url) values(?, ?, ?, ?)", (seasonid,"season","landscape",API().getArtwork(season, "Thumb")))
|
||||||
|
if API().getArtwork(season, "Primary") != "":
|
||||||
|
cursor.execute("INSERT into art(media_id, media_type, type, url) values(?, ?, ?, ?)", (seasonid,"season","poster",API().getArtwork(season, "Primary")))
|
||||||
|
if API().getArtwork(season, "Banner") != "":
|
||||||
|
cursor.execute("INSERT into art(media_id, media_type, type, url) values(?, ?, ?, ?)", (seasonid,"season","banner",API().getArtwork(season, "Banner")))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
@ -873,7 +1103,7 @@ class WriteKodiDB():
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def setKodiFilename(self, id, oldFileName, newFileName, fileType):
|
def setKodiFilename(self, id, oldFileName, newFileName, fileType, mbId):
|
||||||
#use sqlite to set the filename in DB -- needed to avoid problems with resumepoints etc
|
#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
|
#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 --> submit PR to kodi team to get this added to the jsonrpc api
|
||||||
|
@ -889,7 +1119,7 @@ class WriteKodiDB():
|
||||||
|
|
||||||
xbmc.sleep(sleepVal)
|
xbmc.sleep(sleepVal)
|
||||||
connection = utils.KodiSQL()
|
connection = utils.KodiSQL()
|
||||||
cursor = connection.cursor( )
|
cursor = connection.cursor()
|
||||||
utils.logMsg("MB3 Sync","setting filename in kodi db..." + fileType + ": " + str(id))
|
utils.logMsg("MB3 Sync","setting filename in kodi db..." + fileType + ": " + str(id))
|
||||||
utils.logMsg("MB3 Sync","old filename -->" + oldFileName)
|
utils.logMsg("MB3 Sync","old filename -->" + oldFileName)
|
||||||
utils.logMsg("MB3 Sync","new filename -->" + newFileName)
|
utils.logMsg("MB3 Sync","new filename -->" + newFileName)
|
||||||
|
@ -904,17 +1134,21 @@ class WriteKodiDB():
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# we need to store both the path and the filename seperately in the kodi db so we split them up
|
# we need to store both the path and the filename seperately in the kodi db so we split them up
|
||||||
if "\\" in newFileName:
|
|
||||||
filename = newFileName.rsplit("\\",1)[-1]
|
|
||||||
path = newFileName.replace(filename,"")
|
|
||||||
elif "/" in newFileName:
|
|
||||||
filename = newFileName.rsplit("/",1)[-1]
|
|
||||||
path = newFileName.replace(filename,"")
|
|
||||||
|
|
||||||
#if we want to use transcoding/play from stream we pass on the complete http path
|
|
||||||
#in this case both the path and filename are set to the addonpath
|
|
||||||
if newFileName.startswith("http"):
|
if newFileName.startswith("http"):
|
||||||
path = newFileName
|
#transcoding or play from stream
|
||||||
|
path = "plugin://plugin.video.emby/"
|
||||||
|
filename = "?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 ############
|
######### PROCESS EPISODE ############
|
||||||
if fileType == "episode":
|
if fileType == "episode":
|
||||||
|
@ -964,7 +1198,6 @@ class WriteKodiDB():
|
||||||
|
|
||||||
return actionPerformed
|
return actionPerformed
|
||||||
|
|
||||||
|
|
||||||
def AddActorsToMedia(self, KodiItem, people, mediatype):
|
def AddActorsToMedia(self, KodiItem, people, mediatype):
|
||||||
#use sqlite to set add the actors while json api doesn't support this yet
|
#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
|
#todo --> submit PR to kodi team to get this added to the jsonrpc api
|
||||||
|
|
128
service.py
128
service.py
|
@ -36,9 +36,6 @@ class Service():
|
||||||
ConnectionManager().checkServer()
|
ConnectionManager().checkServer()
|
||||||
DownloadUtils().authenticate(retreive=True)
|
DownloadUtils().authenticate(retreive=True)
|
||||||
|
|
||||||
# check kodi library sources
|
|
||||||
mayRun = utils.checkKodiSources()
|
|
||||||
|
|
||||||
player = Player()
|
player = Player()
|
||||||
lastProgressUpdate = datetime.today()
|
lastProgressUpdate = datetime.today()
|
||||||
|
|
||||||
|
@ -48,86 +45,75 @@ class Service():
|
||||||
cur_seconds_fullsync = interval_FullSync
|
cur_seconds_fullsync = interval_FullSync
|
||||||
cur_seconds_incrsync = interval_IncrementalSync
|
cur_seconds_incrsync = interval_IncrementalSync
|
||||||
|
|
||||||
if mayRun:
|
ws = WebSocketThread()
|
||||||
|
|
||||||
ws = WebSocketThread()
|
while not self.KodiMonitor.abortRequested():
|
||||||
|
|
||||||
while not self.KodiMonitor.abortRequested():
|
xbmc.sleep(1000)
|
||||||
|
|
||||||
xbmc.sleep(1000)
|
if xbmc.Player().isPlaying():
|
||||||
|
try:
|
||||||
|
playTime = xbmc.Player().getTime()
|
||||||
|
currentFile = xbmc.Player().getPlayingFile()
|
||||||
|
|
||||||
if xbmc.Player().isPlaying():
|
if(player.played_information.get(currentFile) != None):
|
||||||
try:
|
player.played_information[currentFile]["currentPosition"] = playTime
|
||||||
playTime = xbmc.Player().getTime()
|
|
||||||
currentFile = xbmc.Player().getPlayingFile()
|
|
||||||
|
|
||||||
if(player.played_information.get(currentFile) != None):
|
# send update
|
||||||
player.played_information[currentFile]["currentPosition"] = playTime
|
td = datetime.today() - lastProgressUpdate
|
||||||
|
secDiff = td.seconds
|
||||||
|
if(secDiff > 10):
|
||||||
|
try:
|
||||||
|
player.reportPlayback()
|
||||||
|
except Exception, msg:
|
||||||
|
xbmc.log("MB3 Sync Service -> Exception reporting progress : " + msg)
|
||||||
|
pass
|
||||||
|
lastProgressUpdate = datetime.today()
|
||||||
|
|
||||||
# send update
|
except Exception, e:
|
||||||
td = datetime.today() - lastProgressUpdate
|
xbmc.log("MB3 Sync Service -> Exception in Playback Monitor Service : " + str(e))
|
||||||
secDiff = td.seconds
|
pass
|
||||||
if(secDiff > 10):
|
else:
|
||||||
try:
|
# background worker for database sync
|
||||||
player.reportPlayback()
|
if DownloadUtils().authenticate(retreive=False) != "":
|
||||||
except Exception, msg:
|
|
||||||
xbmc.log("MB3 Sync Service -> Exception reporting progress : " + msg)
|
|
||||||
pass
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
except Exception, e:
|
# Correctly launch the websocket, if user manually launches the add-on
|
||||||
xbmc.log("MB3 Sync Service -> Exception in Playback Monitor Service : " + str(e))
|
if (self.newWebSocketThread == None):
|
||||||
pass
|
self.newWebSocketThread = "Started"
|
||||||
else:
|
ws.start()
|
||||||
# background worker for database sync
|
|
||||||
if DownloadUtils().authenticate(retreive=False) != "":
|
|
||||||
|
|
||||||
# Correctly launch the websocket, if user manually launches the add-on
|
#full sync
|
||||||
if (self.newWebSocketThread == None):
|
if(cur_seconds_fullsync >= interval_FullSync):
|
||||||
self.newWebSocketThread = "Started"
|
xbmc.log("Doing_Db_Sync: syncDatabase (Started)")
|
||||||
ws.start()
|
worked = librarySync.syncDatabase()
|
||||||
|
xbmc.log("Doing_Db_Sync: syncDatabase (Finished) " + str(worked))
|
||||||
#full sync
|
if(worked):
|
||||||
if(cur_seconds_fullsync >= interval_FullSync):
|
cur_seconds_fullsync = 0
|
||||||
xbmc.log("Doing_Db_Sync: syncDatabase (Started)")
|
|
||||||
worked = librarySync.syncDatabase()
|
|
||||||
xbmc.log("Doing_Db_Sync: syncDatabase (Finished) " + str(worked))
|
|
||||||
if(worked):
|
|
||||||
cur_seconds_fullsync = 0
|
|
||||||
else:
|
|
||||||
cur_seconds_fullsync = interval_FullSync - 10
|
|
||||||
else:
|
else:
|
||||||
cur_seconds_fullsync += 1
|
cur_seconds_fullsync = interval_FullSync - 10
|
||||||
|
|
||||||
#incremental sync
|
|
||||||
if(cur_seconds_incrsync >= interval_IncrementalSync):
|
|
||||||
xbmc.log("Doing_Db_Sync: updatePlayCounts (Started)")
|
|
||||||
worked = librarySync.updatePlayCounts()
|
|
||||||
xbmc.log("Doing_Db_Sync: updatePlayCounts (Finished) " + str(worked))
|
|
||||||
if(worked):
|
|
||||||
cur_seconds_incrsync = 0
|
|
||||||
else:
|
|
||||||
cur_seconds_incrsync = interval_IncrementalSync - 10
|
|
||||||
else:
|
|
||||||
cur_seconds_incrsync += 1
|
|
||||||
|
|
||||||
# check if we need to run lib updates
|
|
||||||
WINDOW = xbmcgui.Window( 10000 )
|
|
||||||
if(WINDOW.getProperty("cleanNeeded") == "true"):
|
|
||||||
xbmc.executebuiltin("CleanLibrary(video)")
|
|
||||||
WINDOW.clearProperty("cleanNeeded")
|
|
||||||
|
|
||||||
if(WINDOW.getProperty("updateNeeded") == "true"):
|
|
||||||
xbmc.executebuiltin("UpdateLibrary(video)")
|
|
||||||
WINDOW.clearProperty("updateNeeded")
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
xbmc.log("Not authenticated yet")
|
cur_seconds_fullsync += 1
|
||||||
|
|
||||||
utils.logMsg("MB3 Sync Service", "stopping Service",0)
|
#incremental sync
|
||||||
|
if(cur_seconds_incrsync >= interval_IncrementalSync):
|
||||||
|
xbmc.log("Doing_Db_Sync: updatePlayCounts (Started)")
|
||||||
|
worked = librarySync.updatePlayCounts()
|
||||||
|
xbmc.log("Doing_Db_Sync: updatePlayCounts (Finished) " + str(worked))
|
||||||
|
if(worked):
|
||||||
|
cur_seconds_incrsync = 0
|
||||||
|
else:
|
||||||
|
cur_seconds_incrsync = interval_IncrementalSync - 10
|
||||||
|
else:
|
||||||
|
cur_seconds_incrsync += 1
|
||||||
|
|
||||||
if (self.newWebSocketThread != None):
|
|
||||||
ws.stopClient()
|
else:
|
||||||
|
xbmc.log("Not authenticated yet")
|
||||||
|
|
||||||
|
utils.logMsg("MB3 Sync Service", "stopping Service",0)
|
||||||
|
|
||||||
|
if (self.newWebSocketThread != None):
|
||||||
|
ws.stopClient()
|
||||||
|
|
||||||
|
|
||||||
#start the service
|
#start the service
|
||||||
|
|
Loading…
Reference in a new issue