Use playing item filename and path to find ID
- Fixes #67 - Everything else doesn 't work
This commit is contained in:
parent
be63414893
commit
cfbc7f770c
3 changed files with 115 additions and 127 deletions
|
@ -792,86 +792,83 @@ class Kodidb_Functions():
|
||||||
ids.append(row[0])
|
ids.append(row[0])
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
def getIdFromTitle(self, itemdetails):
|
def getIdFromFilename(self, filename, path):
|
||||||
"""
|
"""
|
||||||
Returns the Kodi id (e.g. idMovie, idEpisode) from the item's
|
Returns the tuple (itemId, type) where
|
||||||
title (c00), if there is exactly ONE found for the itemtype.
|
itemId: Kodi DB unique Id for either movie or episode
|
||||||
(None otherwise)
|
type: either 'movie' or 'episode'
|
||||||
|
|
||||||
itemdetails is the data['item'] response from Kodi
|
Returns None if not found OR if too many entries were found
|
||||||
|
|
||||||
itemdetails for movies:
|
|
||||||
{
|
|
||||||
"title":"Kung Fu Panda",
|
|
||||||
"type":"movie",
|
|
||||||
"year":2008
|
|
||||||
}
|
|
||||||
|
|
||||||
itemdetails for episodes:
|
|
||||||
{
|
|
||||||
"episode":5
|
|
||||||
"season":5,
|
|
||||||
"showtitle":"Girls",
|
|
||||||
"title":"Queen for Two Days",
|
|
||||||
"type":"episode"
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
try:
|
query = ' '.join((
|
||||||
typus = itemdetails['type']
|
"SELECT idFile, idPath",
|
||||||
except:
|
"FROM files",
|
||||||
|
"WHERE strFilename = ?"
|
||||||
|
))
|
||||||
|
self.cursor.execute(query, (filename,))
|
||||||
|
files = self.cursor.fetchall()
|
||||||
|
if len(files) == 0:
|
||||||
|
self.logMsg('Did not find any file, abort', 1)
|
||||||
return
|
return
|
||||||
|
query = ' '.join((
|
||||||
|
"SELECT strPath",
|
||||||
|
"FROM path",
|
||||||
|
"WHERE idPath = ?"
|
||||||
|
))
|
||||||
|
# result will contain a list of all idFile with matching filename and
|
||||||
|
# matching path
|
||||||
|
result = []
|
||||||
|
for file in files:
|
||||||
|
# Use idPath to get path as a string
|
||||||
|
self.cursor.execute(query, (file[1],))
|
||||||
|
try:
|
||||||
|
strPath = self.cursor.fetchone()[0]
|
||||||
|
except TypeError:
|
||||||
|
# idPath not found; skip
|
||||||
|
continue
|
||||||
|
# For whatever reason, double might have become triple
|
||||||
|
strPath = strPath.replace('///', '//')
|
||||||
|
strPath = strPath.replace('\\\\\\', '\\\\')
|
||||||
|
if strPath == path:
|
||||||
|
result.append(file[0])
|
||||||
|
if len(result) == 0:
|
||||||
|
self.logMsg('Did not find matching paths, abort', 1)
|
||||||
|
return
|
||||||
|
self.logMsg('Result: %s' % result)
|
||||||
|
# Kodi seems to make ONE temporary entry; we only want the earlier,
|
||||||
|
# permanent one
|
||||||
|
if len(result) > 2:
|
||||||
|
self.logMsg('We found too many items with matching filenames and '
|
||||||
|
' paths, aborting', 1)
|
||||||
|
return
|
||||||
|
idFile = result[0]
|
||||||
|
self.logMsg('idFile: %s' % idFile)
|
||||||
|
|
||||||
if typus == 'movie':
|
# Try movies first
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
"SELECT idMovie",
|
"SELECT idMovie",
|
||||||
"FROM movie",
|
"FROM movie",
|
||||||
"WHERE c00 = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
|
self.cursor.execute(query, (idFile,))
|
||||||
try:
|
try:
|
||||||
rows = self.cursor.execute(query, (itemdetails['title'],))
|
itemId = self.cursor.fetchone()[0]
|
||||||
except:
|
typus = 'movie'
|
||||||
return
|
except TypeError:
|
||||||
elif typus == 'episode':
|
# Try tv shows next
|
||||||
query = ' '.join((
|
|
||||||
"SELECT idShow",
|
|
||||||
"FROM tvshow",
|
|
||||||
"WHERE c00 = ?"
|
|
||||||
))
|
|
||||||
try:
|
|
||||||
rows = self.cursor.execute(query, (itemdetails['showtitle'],))
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
ids = []
|
|
||||||
for row in rows:
|
|
||||||
ids.append(row[0])
|
|
||||||
if len(ids) > 1:
|
|
||||||
self.logMsg('No unique match possible. Rows: %s' % rows, 1)
|
|
||||||
return
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
"SELECT idEpisode",
|
"SELECT idEpisode",
|
||||||
"FROM episode",
|
"FROM episode",
|
||||||
"WHERE c12 = ? AND c13 = ? AND idShow = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
|
self.cursor.execute(query, (idFile,))
|
||||||
try:
|
try:
|
||||||
rows = self.cursor.execute(
|
itemId = self.cursor.fetchone()[0]
|
||||||
query,
|
typus = 'episode'
|
||||||
(itemdetails['season'],
|
except TypeError:
|
||||||
itemdetails['episode'],
|
self.logMsg('Unexpectantly did not find a match!', 1)
|
||||||
ids[0]))
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
ids = []
|
|
||||||
for row in rows:
|
|
||||||
ids.append(row[0])
|
|
||||||
if len(ids) == 1:
|
|
||||||
return ids[0]
|
|
||||||
else:
|
|
||||||
# No unique match possible
|
|
||||||
return
|
return
|
||||||
|
return itemId, typus
|
||||||
|
|
||||||
def getUnplayedItems(self):
|
def getUnplayedItems(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -177,7 +177,9 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
count += 1
|
count += 1
|
||||||
log("Currently playing file is: %s" % utils.tryDecode(currentFile), 1)
|
# Just to be on the safe side
|
||||||
|
currentFile = utils.tryDecode(currentFile)
|
||||||
|
log("Currently playing file is: %s" % currentFile, 1)
|
||||||
|
|
||||||
# Get the type of media we're playing
|
# Get the type of media we're playing
|
||||||
try:
|
try:
|
||||||
|
@ -185,58 +187,41 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
except (TypeError, KeyError):
|
except (TypeError, KeyError):
|
||||||
log("Item is invalid for PMS playstate update.", 0)
|
log("Item is invalid for PMS playstate update.", 0)
|
||||||
return
|
return
|
||||||
log("Playing itemtype is: %s" % typus, 1)
|
log("Playing itemtype is (or appears to be): %s" % typus, 1)
|
||||||
|
|
||||||
# Try to get a Kodi ID
|
# Try to get a Kodi ID
|
||||||
|
# If PKC was used - native paths, not direct paths
|
||||||
|
plexid = utils.window('emby_%s.itemid'
|
||||||
|
% utils.tryEncode(currentFile))
|
||||||
|
# Get rid of the '' if the window property was not set
|
||||||
|
plexid = None if not plexid else plexid
|
||||||
|
kodiid = None
|
||||||
|
if plexid is None:
|
||||||
|
log('Did not get Plex id from window properties', 1)
|
||||||
try:
|
try:
|
||||||
kodiid = data['item']['id']
|
kodiid = data['item']['id']
|
||||||
except (TypeError, KeyError):
|
except (TypeError, KeyError):
|
||||||
log('Could not get Kodi id directly, trying jsonrpc', 1)
|
log('Did not get a Kodi id from Kodi, darn', 1)
|
||||||
|
# For direct paths, if we're not streaming something
|
||||||
|
# When using Widgets, Kodi doesn't tell us shit so we need this hack
|
||||||
|
if (kodiid is None and plexid is None and typus in ('movie', 'episode')
|
||||||
|
and not currentFile.startswith('http')):
|
||||||
try:
|
try:
|
||||||
playerid = data["player"]["playerid"]
|
filename = currentFile.rsplit('/', 1)[1]
|
||||||
except (TypeError, KeyError):
|
path = currentFile.rsplit('/', 1)[0] + '/'
|
||||||
log("Could not get Kodi playerid. Abort playback report", 0)
|
except IndexError:
|
||||||
return
|
filename = currentFile.rsplit('\\', 1)[1]
|
||||||
# Get details of the playing media
|
path = currentFile.rsplit('\\', 1)[0] + '\\'
|
||||||
result = xbmc.executeJSONRPC(json.dumps({
|
log('Trying to figure out playing item from filename: %s and '
|
||||||
"jsonrpc": "2.0",
|
'path: %s' % (filename, path), 1)
|
||||||
"id": 1,
|
|
||||||
"method": "Player.GetItem",
|
|
||||||
"params": {
|
|
||||||
"playerid": playerid,
|
|
||||||
# Just ask something so we get the item's id (for movies)
|
|
||||||
"properties": [
|
|
||||||
"tvshowid", "title"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
result = json.loads(result)
|
|
||||||
|
|
||||||
kodiid = None
|
|
||||||
if typus in ('movie', 'song'):
|
|
||||||
key = 'id'
|
|
||||||
elif typus == 'episode':
|
|
||||||
key = 'tvshowid'
|
|
||||||
else:
|
|
||||||
log('Unknown type, abort playback report', 1)
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
kodiid = result["result"]["item"][key]
|
|
||||||
except (TypeError, KeyError):
|
|
||||||
pass
|
|
||||||
# Kodi might return -1 for last element
|
|
||||||
if kodiid in (None, -1) and typus in ('movie', 'episode'):
|
|
||||||
log('Could not get Kodi id directly. Kodi said: %s'
|
|
||||||
% result, 1)
|
|
||||||
log('Trying to get Kodi id from the items name', 1)
|
|
||||||
with kodidb.GetKodiDB('video') as kodi_db:
|
with kodidb.GetKodiDB('video') as kodi_db:
|
||||||
kodiid = kodi_db.getIdFromTitle(data.get('item'))
|
try:
|
||||||
|
kodiid, typus = kodi_db.getIdFromFilename(filename, path)
|
||||||
if kodiid in (None, -1):
|
except TypeError:
|
||||||
log("Skip playstate update. No unique Kodi title found"
|
log('Aborting playback report', 1)
|
||||||
" for %s" % data.get('item'), 0)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if plexid is None:
|
||||||
# Get Plex' item id
|
# Get Plex' item id
|
||||||
with embydb.GetEmbyDB() as emby_db:
|
with embydb.GetEmbyDB() as emby_db:
|
||||||
emby_dbitem = emby_db.getItem_byKodiId(kodiid, typus)
|
emby_dbitem = emby_db.getItem_byKodiId(kodiid, typus)
|
||||||
|
@ -246,20 +231,23 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
log("No Plex id returned for kodiid %s" % kodiid, 1)
|
log("No Plex id returned for kodiid %s" % kodiid, 1)
|
||||||
log('Aborting playback report', 1)
|
log('Aborting playback report', 1)
|
||||||
return
|
return
|
||||||
log("Found Plex id %s for Kodi id %s" % (plexid, kodiid), 1)
|
log("Found Plex id %s for Kodi id %s for type %s"
|
||||||
|
% (plexid, kodiid, typus), 1)
|
||||||
|
|
||||||
# Set some stuff if Kodi initiated playback
|
# Set some stuff if Kodi initiated playback
|
||||||
if ((utils.settings('useDirectPaths') == "1" and not typus == "song")
|
if ((utils.settings('useDirectPaths') == "1" and not typus == "song")
|
||||||
or
|
or
|
||||||
(typus == "song" and utils.settings('enableMusic') == "true")):
|
(typus == "song" and utils.settings('enableMusic') == "true")):
|
||||||
if self.StartDirectPath(plexid, typus, currentFile) is False:
|
if self.StartDirectPath(plexid,
|
||||||
|
typus,
|
||||||
|
utils.tryEncode(currentFile)) is False:
|
||||||
log('Could not initiate monitoring; aborting', -1)
|
log('Could not initiate monitoring; aborting', -1)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Save currentFile for cleanup later and to be able to access refs
|
# Save currentFile for cleanup later and to be able to access refs
|
||||||
window('plex_lastPlayedFiled', value=utils.tryDecode(currentFile))
|
window('plex_lastPlayedFiled', value=currentFile)
|
||||||
window('Plex_currently_playing_itemid', value=plexid)
|
window('Plex_currently_playing_itemid', value=plexid)
|
||||||
window("emby_%s.itemid" % currentFile, value=plexid)
|
window("emby_%s.itemid" % utils.tryEncode(currentFile), value=plexid)
|
||||||
log('Finish playback startup', 1)
|
log('Finish playback startup', 1)
|
||||||
|
|
||||||
def StartDirectPath(self, plexid, type, currentFile):
|
def StartDirectPath(self, plexid, type, currentFile):
|
||||||
|
|
|
@ -941,6 +941,9 @@ def tryEncode(uniString, encoding='utf-8'):
|
||||||
uniString = uniString.encode(encoding, "ignore")
|
uniString = uniString.encode(encoding, "ignore")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
uniString = uniString.encode()
|
uniString = uniString.encode()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# already encoded
|
||||||
|
pass
|
||||||
return uniString
|
return uniString
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue