Merge remote-tracking branch 'MediaBrowser/master' into develop
This commit is contained in:
commit
a16b2bdeb3
10 changed files with 528 additions and 344 deletions
|
@ -94,15 +94,15 @@ if __name__ == '__main__':
|
||||||
ret = xbmcgui.Dialog().select(header, options)
|
ret = xbmcgui.Dialog().select(header, options)
|
||||||
if ret != -1:
|
if ret != -1:
|
||||||
if options[ret] == utils.language(30402):
|
if options[ret] == utils.language(30402):
|
||||||
API.updateUserRating(embyid, deletelike=True)
|
emby.updateUserRating(embyid, deletelike=True)
|
||||||
if options[ret] == utils.language(30403):
|
if options[ret] == utils.language(30403):
|
||||||
API.updateUserRating(embyid, like=True)
|
emby.updateUserRating(embyid, like=True)
|
||||||
if options[ret] == utils.language(30404):
|
if options[ret] == utils.language(30404):
|
||||||
API.updateUserRating(embyid, like=False)
|
emby.updateUserRating(embyid, like=False)
|
||||||
if options[ret] == utils.language(30405):
|
if options[ret] == utils.language(30405):
|
||||||
API.updateUserRating(embyid, favourite=True)
|
emby.updateUserRating(embyid, favourite=True)
|
||||||
if options[ret] == utils.language(30406):
|
if options[ret] == utils.language(30406):
|
||||||
API.updateUserRating(embyid, favourite=False)
|
emby.updateUserRating(embyid, favourite=False)
|
||||||
if options[ret] == utils.language(30407):
|
if options[ret] == utils.language(30407):
|
||||||
kodiconn = utils.kodiSQL('music')
|
kodiconn = utils.kodiSQL('music')
|
||||||
kodicursor = kodiconn.cursor()
|
kodicursor = kodiconn.cursor()
|
||||||
|
@ -117,7 +117,7 @@ if __name__ == '__main__':
|
||||||
musicutils.updateRatingToFile(newvalue, API.getFilePath())
|
musicutils.updateRatingToFile(newvalue, API.getFilePath())
|
||||||
if utils.settings('enableExportSongRating') == "true":
|
if utils.settings('enableExportSongRating') == "true":
|
||||||
like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(newvalue)
|
like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(newvalue)
|
||||||
API.updateUserRating(embyid, like, favourite, deletelike)
|
emby.updateUserRating(embyid, like, favourite, deletelike)
|
||||||
query = ' '.join(( "UPDATE song","SET rating = ?", "WHERE idSong = ?" ))
|
query = ' '.join(( "UPDATE song","SET rating = ?", "WHERE idSong = ?" ))
|
||||||
kodicursor.execute(query, (newvalue,itemid,))
|
kodicursor.execute(query, (newvalue,itemid,))
|
||||||
kodiconn.commit()
|
kodiconn.commit()
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
|
||||||
<strings>
|
|
||||||
<string id="30000">Primaire server adres:</string>
|
|
||||||
<string id="30001">Enkele mappen automatisch openen:</string>
|
|
||||||
<string id="30002">Afspelen van stream ipv SMB:</string>
|
|
||||||
<string id="30004">Log niveau:</string>
|
|
||||||
<string id="30005">Gebruikersnaam: </string>
|
|
||||||
<string id="30006">Wachtwoord: </string>
|
|
||||||
<string id="30007">Samba gebruikersnaam: </string>
|
|
||||||
<string id="30008">Samba wachtwoord: </string>
|
|
||||||
<string id="30009">Transcode: </string>
|
|
||||||
<string id="30010">Prestatie profilering inschakelen:</string>
|
|
||||||
<string id="30011">Lokale cache systeem</string>
|
|
||||||
|
|
||||||
<string id="30014">Emby</string>
|
|
||||||
<string id="30015">Netwerk</string>
|
|
||||||
<string id="30016">Apparaatnaam</string>
|
|
||||||
|
|
||||||
<string id="30022">Geavanceerd</string>
|
|
||||||
<string id="30024">Gebruikersnaam:</string>
|
|
||||||
<string id="30025">Wachtwoord:</string>
|
|
||||||
<string id="30026">Gebruik SIMPLEJSON ipv JSON</string>
|
|
||||||
|
|
||||||
<string id="30030">Poortnummer:</string>
|
|
||||||
<string id="30036">Aantal recente films die getoond worden:</string>
|
|
||||||
<string id="30037">Aantal recente TV-series die getoond worden:</string>
|
|
||||||
<string id="30035">Aantal recente muziekalbums die getoond worden:</string>
|
|
||||||
<string id="30038">Markeer als bekeken bij starten van afspelen:</string>
|
|
||||||
<string id="30039">Gebruik seizoen poster bij afleveringen</string>
|
|
||||||
|
|
||||||
<string id="30040">Genre filter ...</string>
|
|
||||||
<string id="30041">Speel alles vanaf hier</string>
|
|
||||||
<string id="30042">Vernieuwen</string>
|
|
||||||
<string id="30043">Wissen</string>
|
|
||||||
<string id="30046">Voeg film toe aan CouchPotato</string>
|
|
||||||
|
|
||||||
<string id="30044">Ongeldige gebruikersnaam/wachtwoord</string>
|
|
||||||
<string id="30045">Gebruikersnaam niet gevonden</string>
|
|
||||||
|
|
||||||
<string id="30052">Wissen...</string>
|
|
||||||
<string id="30053">Wacht op server voor wissen</string>
|
|
||||||
|
|
||||||
<string id="30059">Server standaard</string>
|
|
||||||
<string id="30060">Titel</string>
|
|
||||||
<string id="30061">Jaar</string>
|
|
||||||
<string id="30062">Premiere datum</string>
|
|
||||||
<string id="30063">Datum toegevoegd</string>
|
|
||||||
<string id="30064">Critici beoordeling</string>
|
|
||||||
<string id="30065">Community beoordeling</string>
|
|
||||||
<string id="30066">Aantal keer bekeken</string>
|
|
||||||
<string id="30067">Budget</string>
|
|
||||||
|
|
||||||
<string id="30068">Sorteer op</string>
|
|
||||||
|
|
||||||
<string id="30069">Geen</string>
|
|
||||||
<string id="30070">Actie</string>
|
|
||||||
<string id="30071">Avontuur</string>
|
|
||||||
<string id="30072">Animatie</string>
|
|
||||||
<string id="30073">Misdaad</string>
|
|
||||||
<string id="30074">Comedy</string>
|
|
||||||
<string id="30075">Documentaire</string>
|
|
||||||
<string id="30076">Drama</string>
|
|
||||||
<string id="30077">Fantasie</string>
|
|
||||||
<string id="30078">Nederlands</string>
|
|
||||||
<string id="30079">Historie</string>
|
|
||||||
<string id="30080">Horror</string>
|
|
||||||
<string id="30081">Muziek</string>
|
|
||||||
<string id="30082">Musical</string>
|
|
||||||
<string id="30083">Mysterie</string>
|
|
||||||
<string id="30084">Romantiek</string>
|
|
||||||
<string id="30085">Science Fiction</string>
|
|
||||||
<string id="30086">Kort</string>
|
|
||||||
<string id="30087">Spanning</string>
|
|
||||||
<string id="30088">Thriller</string>
|
|
||||||
<string id="30089">Western</string>
|
|
||||||
|
|
||||||
<string id="30090">Genre filter</string>
|
|
||||||
<string id="30091">Bevestig wissen</string>
|
|
||||||
<string id="30092">Dit item wissen ? Dit zal het bestand volledig verwijderen.</string>
|
|
||||||
|
|
||||||
<string id="30093">Markeer als bekeken</string>
|
|
||||||
<string id="30094">Mark als onbekeken</string>
|
|
||||||
<string id="30095">Voeg toe aan favorieten</string>
|
|
||||||
<string id="30096">Verwijder uit favorieten</string>
|
|
||||||
<string id="30097">Sorteer op...</string>
|
|
||||||
<string id="30098">Sorteer oplopend</string>
|
|
||||||
<string id="30099">Sorteer aflopend</string>
|
|
||||||
<string id="30100">Toon acteurs</string>
|
|
||||||
|
|
||||||
<!-- resume dialog -->
|
|
||||||
<string id="30105">Hervatten</string>
|
|
||||||
<string id="30106">Hervatten vanaf</string>
|
|
||||||
<string id="30107">Start vanaf begin</string>
|
|
||||||
|
|
||||||
<string id="30110">Interface</string>
|
|
||||||
<string id="30111">Inclusief stream info</string>
|
|
||||||
<string id="30112">Inclusief personen</string>
|
|
||||||
<string id="30113">Inclusief filminfo</string>
|
|
||||||
<string id="30114">Bij hervatten aantal seconden terugspringen</string>
|
|
||||||
<string id="30115">Markeer als bekeken wanneer na percentage gestopt</string>
|
|
||||||
<string id="30116">Inclusief aantal en afspeel tellers</string>
|
|
||||||
<string id="30117"> - Achtergrond plaatjes verversen (secondes)</string>
|
|
||||||
<string id="30118">Inclusief hervat-percentage</string>
|
|
||||||
<string id="30119">Afleveringnummer tonen in titel</string>
|
|
||||||
<string id="30120">Toon voortgang</string>
|
|
||||||
<string id="30121">Laden van content</string>
|
|
||||||
<string id="30122">Retrieving Data</string>
|
|
||||||
<string id="30123">Parsing Jason Data</string>
|
|
||||||
<string id="30124">Downloading Jason Data</string>
|
|
||||||
<string id="30125">Done</string>
|
|
||||||
<string id="30126">Processing Item : </string>
|
|
||||||
<string id="30127">Toon wismogelijkheid na bekijken van aflevering</string>
|
|
||||||
<string id="30128">Afspeelfout!</string>
|
|
||||||
<string id="30129">Dit item kan niet worden afgespeeld</string>
|
|
||||||
<string id="30130">Lockaal pad gedetecteerd</string>
|
|
||||||
<string id="30131">De MB3 bibliotheek bevat lokale paden. U moet UNC-paden gebruiken of afspelen van stream inschakelen. Pad: </string>
|
|
||||||
<string id="30132">Waarschuwing</string>
|
|
||||||
<string id="30133">Debug logging ingeschakeld.</string>
|
|
||||||
<string id="30134">Dit heeft effect op de performance.</string>
|
|
||||||
<string id="30135">Fout</string>
|
|
||||||
<string id="30136">XBMB3C service werkt niet</string>
|
|
||||||
<string id="30137">Herstart XBMC aub</string>
|
|
||||||
<string id="30138">Zoeken</string>
|
|
||||||
|
|
||||||
<string id="30139">Schakel Themamuziek in (vereist herstart)</string>
|
|
||||||
<string id="30140"> - Herhalen van themamuziek</string>
|
|
||||||
<string id="30141">Activeer achtergrondafbeelding (vereist herstart)</string>
|
|
||||||
<string id="30142">Services</string>
|
|
||||||
<string id="30143">Activeer Info Loader (vereist herstart)</string>
|
|
||||||
<string id="30144">Activeer Menu Loader (vereist herstart)</string>
|
|
||||||
<string id="30145">Activeer WebSocket Remote (vereist herstart)</string>
|
|
||||||
<string id="30146">Activeer In Progress Loader (vereist herstart)</string>
|
|
||||||
<string id="30147">Activeer Recent Info Loader (vereist herstart)</string>
|
|
||||||
<string id="30148">Activeer Random Loader (vereist herstart)</string>
|
|
||||||
<string id="30149">Activeer Next Up Loader (vereist herstart)</string>
|
|
||||||
|
|
||||||
<string id="30150">Skin ondersteund het vastleggen van views niet</string>
|
|
||||||
<string id="30151">Selecteer item actie (vereist herstart)</string>
|
|
||||||
|
|
||||||
<string id="30152">Toon indactors</string>
|
|
||||||
<string id="30153"> - Toon bekeken indator</string>
|
|
||||||
<string id="30154"> - Toon aantal onbekeken indicator</string>
|
|
||||||
<string id="30155"> - Toon afspeel-percentage indicator</string>
|
|
||||||
<string id="30156">Sorteer volgende (NextUp) op titel</string>
|
|
||||||
<string id="30157">Deactiveer speciale afbeeldingen (bv CoverArt)</string>
|
|
||||||
<string id="30158">Metadata</string>
|
|
||||||
<string id="30159">Afbeeldingen</string>
|
|
||||||
<string id="30160">Video kwaliteit</string>
|
|
||||||
|
|
||||||
<string id="30161">Activeer Suggested Loader (vereist herstart)</string>
|
|
||||||
<string id="30162">Seizoen tonen in titel</string>
|
|
||||||
<string id="30163">Seizoenen verbergen</string>
|
|
||||||
|
|
||||||
<string id="30164">Direct Play - HTTP</string>
|
|
||||||
<string id="30165">Direct Play</string>
|
|
||||||
<string id="30166">Transcoding</string>
|
|
||||||
<string id="30167">Server Detection Succeeded</string>
|
|
||||||
<string id="30168">Found server</string>
|
|
||||||
<string id="30169">Address : </string>
|
|
||||||
|
|
||||||
|
|
||||||
<string id="30170">Recent toegevoegde TV-series</string>
|
|
||||||
<string id="30171">Niet afgekeken TV-series</string>
|
|
||||||
|
|
||||||
<string id="30172">Alle Muziek</string>
|
|
||||||
<string id="30173">Kanalen</string>
|
|
||||||
<string id="30174">Recent toegevoegde films</string>
|
|
||||||
<string id="30175">Recent toegevoegde afleveringen</string>
|
|
||||||
<string id="30176">Recent toegevoegde albums</string>
|
|
||||||
<string id="30177">Niet afgekeken films</string>
|
|
||||||
<string id="30178">Niet afgekeken afleveringen</string>
|
|
||||||
<string id="30179">NextUp afleveringen</string>
|
|
||||||
<string id="30180">Favoriete films</string>
|
|
||||||
<string id="30181">Favoriete TV-series</string>
|
|
||||||
<string id="30182">Favoriete afleveringen</string>
|
|
||||||
<string id="30183">Vaak afgespeelde albums</string>
|
|
||||||
<string id="30184">Upcoming TV</string>
|
|
||||||
<string id="30185">BoxSets</string>
|
|
||||||
<string id="30186">Trailers</string>
|
|
||||||
<string id="30187">Muziek videos</string>
|
|
||||||
<string id="30188">Fotos</string>
|
|
||||||
<string id="30189">Onbekeken films</string>
|
|
||||||
|
|
||||||
<string id="30191">Film Studios</string>
|
|
||||||
<string id="30192">Film Acteurs</string>
|
|
||||||
<string id="30193">Onbekeken afleveringen</string>
|
|
||||||
<string id="30194">TV Genres</string>
|
|
||||||
<string id="30195">TV Networks</string>
|
|
||||||
<string id="30196">TV Acteurs</string>
|
|
||||||
<string id="30197">Afspeellijsten</string>
|
|
||||||
<string id="30198">Zoeken</string>
|
|
||||||
<string id="30199">Views instellen</string>
|
|
||||||
|
|
||||||
<string id="30200">Selecteer gebruiker</string>
|
|
||||||
<string id="30201">Profilering ingeschakeld.</string>
|
|
||||||
<string id="30202">Svp onthouden om weer uit te schakelen na het testen.</string>
|
|
||||||
<string id="30203">Error in ArtworkRotationThread</string>
|
|
||||||
<string id="30204">Kan niet verbinden met server</string>
|
|
||||||
<string id="30205">Error in LoadMenuOptionsThread</string>
|
|
||||||
|
|
||||||
<string id="30206">Activeer Playlists Loader (vereist herstart)</string>
|
|
||||||
|
|
||||||
<string id="30207">Liedjes</string>
|
|
||||||
<string id="30208">Albums</string>
|
|
||||||
<string id="30209">Album artiesten</string>
|
|
||||||
<string id="30210">Artiesten</string>
|
|
||||||
<string id="30211">Muziek Genres</string>
|
|
||||||
|
|
||||||
<string id="30212">Schakel Themavideos in (vereist herstart)</string>
|
|
||||||
<string id="30213"> - Herhalen van themavideos</string>
|
|
||||||
|
|
||||||
<string id="30214">Schakel het forceren van view uit</string>
|
|
||||||
<string id="30215">Schakel snelle modus in (beta)</string>
|
|
||||||
<string id="30216">Automatisch resterende afleveringen in een seizoen afspelen</string>
|
|
||||||
<string id="30217">Boxsets tonen in de overzichten (vereist herstart)</string>
|
|
||||||
<string id="30218">Afbeeldingen comprimeren</string>
|
|
||||||
<string id="30219">Activeer Skin Helper (vereust herstart)</string>
|
|
||||||
<string id="30220">Laatste </string>
|
|
||||||
<string id="30221">Bezig </string>
|
|
||||||
<string id="30222">Volgende </string>
|
|
||||||
<string id="30223">Gebruikerweergaven </string>
|
|
||||||
|
|
||||||
<!-- Default views -->
|
|
||||||
<string id="30300">Actief</string>
|
|
||||||
<string id="30301">Herstel standaard</string>
|
|
||||||
<string id="30302">Films</string>
|
|
||||||
<string id="30303">BoxSets</string>
|
|
||||||
<string id="30304">Trailers</string>
|
|
||||||
<string id="30305">Series</string>
|
|
||||||
<string id="30306">Seizoenen</string>
|
|
||||||
<string id="30307">Afleveringen</string>
|
|
||||||
<string id="30308">Muziek - artiesten</string>
|
|
||||||
<string id="30309">Muziek - albums</string>
|
|
||||||
<string id="30310">Muziekvideos</string>
|
|
||||||
<string id="30311">Muziek - liedjes</string>
|
|
||||||
<string id="30312">Kanalen</string>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</strings>
|
|
|
@ -500,7 +500,7 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
|
|
||||||
server = self.server
|
server = self.server
|
||||||
|
|
||||||
id = item['Id']
|
itemid = item['Id']
|
||||||
artworks = item['ImageTags']
|
artworks = item['ImageTags']
|
||||||
backdrops = item.get('BackdropImageTags',[])
|
backdrops = item.get('BackdropImageTags',[])
|
||||||
|
|
||||||
|
@ -526,15 +526,12 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Process backdrops
|
# Process backdrops
|
||||||
backdropIndex = 0
|
for index, tag in enumerate(backdrops):
|
||||||
for backdroptag in backdrops:
|
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, id, backdropIndex,
|
% (server, itemid, index, maxWidth, maxHeight, tag, customquery))
|
||||||
maxWidth, maxHeight, backdroptag, customquery))
|
|
||||||
allartworks['Backdrop'].append(artwork)
|
allartworks['Backdrop'].append(artwork)
|
||||||
backdropIndex += 1
|
|
||||||
|
|
||||||
# Process the rest of the artwork
|
# Process the rest of the artwork
|
||||||
for art in artworks:
|
for art in artworks:
|
||||||
|
@ -544,7 +541,7 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/%s/0?"
|
"%s/emby/Items/%s/Images/%s/0?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, id, art, maxWidth, maxHeight, tag, customquery))
|
% (server, itemid, art, maxWidth, maxHeight, tag, customquery))
|
||||||
allartworks[art] = artwork
|
allartworks[art] = artwork
|
||||||
|
|
||||||
# Process parent items if the main item is missing artwork
|
# Process parent items if the main item is missing artwork
|
||||||
|
@ -558,15 +555,12 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
# If there is a parentId, go through the parent backdrop list
|
# If there is a parentId, go through the parent backdrop list
|
||||||
parentbackdrops = item['ParentBackdropImageTags']
|
parentbackdrops = item['ParentBackdropImageTags']
|
||||||
|
|
||||||
backdropIndex = 0
|
for index, tag in enumerate(parentbackdrops):
|
||||||
for parentbackdroptag in parentbackdrops:
|
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, parentId, backdropIndex,
|
% (server, parentId, index, maxWidth, maxHeight, tag, customquery))
|
||||||
maxWidth, maxHeight, parentbackdroptag, customquery))
|
|
||||||
allartworks['Backdrop'].append(artwork)
|
allartworks['Backdrop'].append(artwork)
|
||||||
backdropIndex += 1
|
|
||||||
|
|
||||||
# Process the rest of the artwork
|
# Process the rest of the artwork
|
||||||
parentartwork = ['Logo', 'Art', 'Thumb']
|
parentartwork = ['Logo', 'Art', 'Thumb']
|
||||||
|
|
269
resources/lib/connect.py
Normal file
269
resources/lib/connect.py
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import utils
|
||||||
|
import clientinfo
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
|
||||||
|
# Disable requests logging
|
||||||
|
from requests.packages.urllib3.exceptions import InsecureRequestWarning, InsecurePlatformWarning
|
||||||
|
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||||
|
requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
|
||||||
|
#logging.getLogger('requests').setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectUtils():
|
||||||
|
|
||||||
|
# Borg - multiple instances, shared state
|
||||||
|
_shared_state = {}
|
||||||
|
clientInfo = clientinfo.ClientInfo()
|
||||||
|
addonName = clientInfo.getAddonName()
|
||||||
|
|
||||||
|
# Requests session
|
||||||
|
c = None
|
||||||
|
timeout = 30
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.__dict__ = self._shared_state
|
||||||
|
|
||||||
|
def logMsg(self, msg, lvl=1):
|
||||||
|
|
||||||
|
className = self.__class__.__name__
|
||||||
|
utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
|
||||||
|
|
||||||
|
|
||||||
|
def setUserId(self, userId):
|
||||||
|
# Reserved for userclient only
|
||||||
|
self.userId = userId
|
||||||
|
self.logMsg("Set connect userId: %s" % userId, 2)
|
||||||
|
|
||||||
|
def setServer(self, server):
|
||||||
|
# Reserved for userclient only
|
||||||
|
self.server = server
|
||||||
|
self.logMsg("Set connect server: %s" % server, 2)
|
||||||
|
|
||||||
|
def setToken(self, token):
|
||||||
|
# Reserved for userclient only
|
||||||
|
self.token = token
|
||||||
|
self.logMsg("Set connect token: %s" % token, 2)
|
||||||
|
|
||||||
|
|
||||||
|
def startSession(self):
|
||||||
|
|
||||||
|
log = self.logMsg
|
||||||
|
|
||||||
|
self.deviceId = self.clientInfo.getDeviceId()
|
||||||
|
|
||||||
|
# User is identified from this point
|
||||||
|
# Attach authenticated header to the session
|
||||||
|
verify = False
|
||||||
|
header = self.getHeader()
|
||||||
|
|
||||||
|
# If user enabled host certificate verification
|
||||||
|
try:
|
||||||
|
verify = self.sslverify
|
||||||
|
if self.sslclient is not None:
|
||||||
|
verify = self.sslclient
|
||||||
|
except:
|
||||||
|
log("Could not load SSL settings.", 1)
|
||||||
|
|
||||||
|
# Start session
|
||||||
|
self.c = requests.Session()
|
||||||
|
self.c.headers = header
|
||||||
|
self.c.verify = verify
|
||||||
|
# Retry connections to the server
|
||||||
|
self.c.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||||
|
self.c.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||||
|
|
||||||
|
log("Requests session started on: %s" % self.server, 1)
|
||||||
|
|
||||||
|
def stopSession(self):
|
||||||
|
try:
|
||||||
|
self.c.close()
|
||||||
|
except Exception as e:
|
||||||
|
self.logMsg("Requests session could not be terminated: %s" % e, 1)
|
||||||
|
|
||||||
|
def getHeader(self, authenticate=True):
|
||||||
|
|
||||||
|
clientInfo = self.clientInfo
|
||||||
|
version = clientInfo.getVersion()
|
||||||
|
|
||||||
|
if not authenticate:
|
||||||
|
# If user is not authenticated
|
||||||
|
header = {
|
||||||
|
|
||||||
|
'X-Application': "Kodi/%s" % version,
|
||||||
|
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'Accept': "application/json"
|
||||||
|
}
|
||||||
|
self.logMsg("Header: %s" % header, 1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
token = self.token
|
||||||
|
# Attached to the requests session
|
||||||
|
header = {
|
||||||
|
|
||||||
|
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'Accept': "application/json",
|
||||||
|
'X-Application': "Kodi/%s" % version,
|
||||||
|
'X-Connect-UserToken': token
|
||||||
|
}
|
||||||
|
self.logMsg("Header: %s" % header, 1)
|
||||||
|
|
||||||
|
return header
|
||||||
|
|
||||||
|
def doUrl(self, url, data=None, postBody=None, rtype="GET",
|
||||||
|
parameters=None, authenticate=True, timeout=None):
|
||||||
|
|
||||||
|
log = self.logMsg
|
||||||
|
window = utils.window
|
||||||
|
|
||||||
|
log("=== ENTER connectUrl ===", 2)
|
||||||
|
default_link = ""
|
||||||
|
if timeout is None:
|
||||||
|
timeout = self.timeout
|
||||||
|
|
||||||
|
# Get requests session
|
||||||
|
try:
|
||||||
|
# If connect user is authenticated
|
||||||
|
if authenticate:
|
||||||
|
try:
|
||||||
|
c = self.c
|
||||||
|
# Replace for the real values
|
||||||
|
url = url.replace("{server}", self.server)
|
||||||
|
url = url.replace("{UserId}", self.userId)
|
||||||
|
|
||||||
|
# Prepare request
|
||||||
|
if rtype == "GET":
|
||||||
|
r = c.get(url, json=postBody, params=parameters, timeout=timeout)
|
||||||
|
elif rtype == "POST":
|
||||||
|
r = c.post(url, data=data, timeout=timeout)
|
||||||
|
elif rtype == "DELETE":
|
||||||
|
r = c.delete(url, json=postBody, timeout=timeout)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
# request session does not exists
|
||||||
|
self.server = "https://connect.emby.media/service"
|
||||||
|
self.userId = window('embyco_currUser')
|
||||||
|
self.token = window('embyco_accessToken%s' % self.userId)
|
||||||
|
|
||||||
|
header = self.getHeader()
|
||||||
|
verifyssl = False
|
||||||
|
|
||||||
|
# If user enables ssl verification
|
||||||
|
try:
|
||||||
|
verifyssl = self.sslverify
|
||||||
|
if self.sslclient is not None:
|
||||||
|
verifyssl = self.sslclient
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Prepare request
|
||||||
|
if rtype == "GET":
|
||||||
|
r = requests.get(url,
|
||||||
|
json=postBody,
|
||||||
|
params=parameters,
|
||||||
|
headers=header,
|
||||||
|
timeout=timeout,
|
||||||
|
verify=verifyssl)
|
||||||
|
|
||||||
|
elif rtype == "POST":
|
||||||
|
r = requests.post(url,
|
||||||
|
data=data,
|
||||||
|
headers=header,
|
||||||
|
timeout=timeout,
|
||||||
|
verify=verifyssl)
|
||||||
|
# If user is not authenticated
|
||||||
|
else:
|
||||||
|
header = self.getHeader(authenticate=False)
|
||||||
|
verifyssl = False
|
||||||
|
|
||||||
|
# If user enables ssl verification
|
||||||
|
try:
|
||||||
|
verifyssl = self.sslverify
|
||||||
|
if self.sslclient is not None:
|
||||||
|
verifyssl = self.sslclient
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Prepare request
|
||||||
|
if rtype == "GET":
|
||||||
|
r = requests.get(url,
|
||||||
|
json=postBody,
|
||||||
|
params=parameters,
|
||||||
|
headers=header,
|
||||||
|
timeout=timeout,
|
||||||
|
verify=verifyssl)
|
||||||
|
|
||||||
|
elif rtype == "POST":
|
||||||
|
r = requests.post(url,
|
||||||
|
data=data,
|
||||||
|
headers=header,
|
||||||
|
timeout=timeout,
|
||||||
|
verify=verifyssl)
|
||||||
|
|
||||||
|
##### THE RESPONSE #####
|
||||||
|
log(r.url, 1)
|
||||||
|
log(r, 1)
|
||||||
|
|
||||||
|
if r.status_code == 204:
|
||||||
|
# No body in the response
|
||||||
|
log("====== 204 Success ======", 1)
|
||||||
|
|
||||||
|
elif r.status_code == requests.codes.ok:
|
||||||
|
|
||||||
|
try:
|
||||||
|
# UNICODE - JSON object
|
||||||
|
r = r.json()
|
||||||
|
log("====== 200 Success ======", 1)
|
||||||
|
log("Response: %s" % r, 1)
|
||||||
|
return r
|
||||||
|
|
||||||
|
except:
|
||||||
|
if r.headers.get('content-type') != "text/html":
|
||||||
|
log("Unable to convert the response for: %s" % url, 1)
|
||||||
|
else:
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
##### EXCEPTIONS #####
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectionError as e:
|
||||||
|
# Make the addon aware of status
|
||||||
|
pass
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectTimeout as e:
|
||||||
|
log("Server timeout at: %s" % url, 0)
|
||||||
|
log(e, 1)
|
||||||
|
|
||||||
|
except requests.exceptions.HTTPError as e:
|
||||||
|
|
||||||
|
if r.status_code == 401:
|
||||||
|
# Unauthorized
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif r.status_code in (301, 302):
|
||||||
|
# Redirects
|
||||||
|
pass
|
||||||
|
elif r.status_code == 400:
|
||||||
|
# Bad requests
|
||||||
|
pass
|
||||||
|
|
||||||
|
except requests.exceptions.SSLError as e:
|
||||||
|
log("Invalid SSL certificate for: %s" % url, 0)
|
||||||
|
log(e, 1)
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
log("Unknown error connecting to: %s" % url, 0)
|
||||||
|
log(e, 1)
|
||||||
|
|
||||||
|
return default_link
|
|
@ -184,6 +184,21 @@ class Embydb_Functions():
|
||||||
return item
|
return item
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
|
def getItem_byWildId(self, embyid):
|
||||||
|
|
||||||
|
embycursor = self.embycursor
|
||||||
|
|
||||||
|
query = ' '.join((
|
||||||
|
|
||||||
|
"SELECT kodi_id, media_type",
|
||||||
|
"FROM emby",
|
||||||
|
"WHERE emby_id LIKE ?"
|
||||||
|
))
|
||||||
|
embycursor.execute(query, (embyid+"%",))
|
||||||
|
items = embycursor.fetchall()
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
||||||
def getItem_byView(self, mediafolderid):
|
def getItem_byView(self, mediafolderid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
embycursor = self.embycursor
|
||||||
|
@ -358,3 +373,9 @@ class Embydb_Functions():
|
||||||
|
|
||||||
query = "DELETE FROM emby WHERE emby_id = ?"
|
query = "DELETE FROM emby WHERE emby_id = ?"
|
||||||
self.embycursor.execute(query, (embyid,))
|
self.embycursor.execute(query, (embyid,))
|
||||||
|
|
||||||
|
def removeWildItem(self, embyid):
|
||||||
|
|
||||||
|
query = "DELETE FROM emby WHERE emby_id LIKE ?"
|
||||||
|
self.embycursor.execute(query, (embyid+"%",))
|
||||||
|
|
|
@ -2008,6 +2008,7 @@ class Music(Items):
|
||||||
# Process single song
|
# Process single song
|
||||||
kodiversion = self.kodiversion
|
kodiversion = self.kodiversion
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
|
emby = self.emby
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
kodi_db = self.kodi_db
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
|
@ -2132,14 +2133,22 @@ class Music(Items):
|
||||||
item.attrib.get('parentRatingKey'))
|
item.attrib.get('parentRatingKey'))
|
||||||
albumid = emby_dbalbum[0]
|
albumid = emby_dbalbum[0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# No album Id associated to the song.
|
# Verify if there's an album associated.
|
||||||
self.logMsg("Song itemid: %s has no albumId." % itemid, 1)
|
album_name = item.get('Album')
|
||||||
return
|
if album_name:
|
||||||
|
self.logMsg("Creating virtual music album for song: %s." % itemid, 1)
|
||||||
|
albumid = kodi_db.addAlbum(album_name, API.getProvider('MusicBrainzAlbum'))
|
||||||
|
emby_db.addReference("%salbum%s" % (itemid, albumid), albumid, "MusicAlbum_", "album")
|
||||||
|
else:
|
||||||
|
# No album Id associated to the song.
|
||||||
|
self.logMsg("Song itemid: %s has no albumId associated." % itemid, 1)
|
||||||
|
return False
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# No album found. Let's create it
|
# No album found. Let's create it
|
||||||
self.logMsg("Album database entry missing.", 1)
|
self.logMsg("Album database entry missing.", 1)
|
||||||
emby_albumId = item.attrib.get('parentRatingKey')
|
emby_albumId = item.attrib.get('parentRatingKey')
|
||||||
album = GetPlexMetadata(emby_albumId)
|
album = emby.getItem(emby_albumId)
|
||||||
self.add_updateAlbum(album)
|
self.add_updateAlbum(album)
|
||||||
emby_dbalbum = emby_db.getItem_byId(emby_albumId)
|
emby_dbalbum = emby_db.getItem_byId(emby_albumId)
|
||||||
try:
|
try:
|
||||||
|
@ -2214,43 +2223,47 @@ class Music(Items):
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
kodicursor.execute(query, (songid, albumid, track, title, duration))
|
kodicursor.execute(query, (songid, albumid, track, title, duration))
|
||||||
# Verify if album has artists
|
# Link song to artists
|
||||||
addArtist = False
|
for index, artist in enumerate(item['ArtistItems']):
|
||||||
query = ' '.join((
|
|
||||||
|
|
||||||
"SELECT strArtists",
|
artist_name = artist['Name']
|
||||||
"FROM album",
|
artist_eid = artist['Id']
|
||||||
"WHERE idAlbum = ?"
|
artist_edb = emby_db.getItem_byId(artist_eid)
|
||||||
))
|
try:
|
||||||
kodicursor.execute(query, (albumid,))
|
artistid = artist_edb[0]
|
||||||
result = kodicursor.fetchone()
|
except TypeError:
|
||||||
if result and result[0] == "":
|
# Artist is missing from emby database, add it.
|
||||||
addArtist = True
|
artist_full = emby.getItem(artist_eid)
|
||||||
|
self.add_updateArtist(artist_full)
|
||||||
|
artist_edb = emby_db.getItem_byId(artist_eid)
|
||||||
|
artistid = artist_edb[0]
|
||||||
|
finally:
|
||||||
|
query = (
|
||||||
|
'''
|
||||||
|
INSERT OR REPLACE INTO song_artist(idArtist, idSong, iOrder, strArtist)
|
||||||
|
|
||||||
# if item['AlbumArtists']:
|
VALUES (?, ?, ?, ?)
|
||||||
# album_artists = item['AlbumArtists']
|
'''
|
||||||
# else:
|
)
|
||||||
# album_artists = item['ArtistItems']
|
kodicursor.execute(query, (artistid, songid, index, artist_name))
|
||||||
|
|
||||||
# Link song to artist
|
# Verify if album artist exists
|
||||||
artist_name = item.attrib.get('grandparentTitle')
|
album_artists = []
|
||||||
emby_dbartist = emby_db.getItem_byId(
|
for artist in item['AlbumArtists']:
|
||||||
item.attrib.get('grandparentRatingKey'))
|
|
||||||
try:
|
|
||||||
artistid = emby_dbartist[0]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
query = (
|
|
||||||
'''
|
|
||||||
INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist)
|
|
||||||
|
|
||||||
VALUES (?, ?, ?)
|
artist_name = artist['Name']
|
||||||
'''
|
album_artists.append(artist_name)
|
||||||
)
|
artist_eid = artist['Id']
|
||||||
kodicursor.execute(query, (artistid, songid, artist_name))
|
artist_edb = emby_db.getItem_byId(artist_eid)
|
||||||
|
try:
|
||||||
if addArtist:
|
artistid = artist_edb[0]
|
||||||
|
except TypeError:
|
||||||
|
# Artist is missing from emby database, add it.
|
||||||
|
artist_full = emby.getItem(artist_eid)
|
||||||
|
self.add_updateArtist(artist_full)
|
||||||
|
artist_edb = emby_db.getItem_byId(artist_eid)
|
||||||
|
artistid = artist_edb[0]
|
||||||
|
finally:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
|
INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
|
||||||
|
@ -2259,17 +2272,101 @@ class Music(Items):
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
kodicursor.execute(query, (artistid, albumid, artist_name))
|
kodicursor.execute(query, (artistid, albumid, artist_name))
|
||||||
|
# Update discography
|
||||||
|
if item.get('Album'):
|
||||||
|
query = (
|
||||||
|
'''
|
||||||
|
INSERT OR REPLACE INTO discography(idArtist, strAlbum, strYear)
|
||||||
|
|
||||||
if addArtist:
|
VALUES (?, ?, ?)
|
||||||
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
'''
|
||||||
kodicursor.execute(query, (artist_name, albumid))
|
)
|
||||||
|
kodicursor.execute(query, (artistid, item['Album'], 0))
|
||||||
|
else:
|
||||||
|
album_artists = " / ".join(album_artists)
|
||||||
|
query = ' '.join((
|
||||||
|
|
||||||
|
"SELECT strArtists",
|
||||||
|
"FROM album",
|
||||||
|
"WHERE idAlbum = ?"
|
||||||
|
))
|
||||||
|
kodicursor.execute(query, (albumid,))
|
||||||
|
result = kodicursor.fetchone()
|
||||||
|
if result and result[0] != album_artists:
|
||||||
|
# Field is empty
|
||||||
|
if kodiversion in (16, 17):
|
||||||
|
# Kodi Jarvis, Krypton
|
||||||
|
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
||||||
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
|
elif kodiversion == 15:
|
||||||
|
# Kodi Isengard
|
||||||
|
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
||||||
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
|
else:
|
||||||
|
# Kodi Helix
|
||||||
|
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
||||||
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
|
|
||||||
# Add genres
|
# Add genres
|
||||||
kodi_db.addMusicGenres(songid, genres, "song")
|
kodi_db.addMusicGenres(songid, genres, "song")
|
||||||
|
|
||||||
# Update artwork
|
# Update artwork
|
||||||
allart = API.getAllArtwork(parentInfo=True)
|
allart = API.getAllArtwork(parentInfo=True)
|
||||||
artwork.addArtwork(allart, songid, "song", kodicursor)
|
artwork.addArtwork(allart, songid, "song", kodicursor)
|
||||||
|
|
||||||
|
if item.get('AlbumId') is None:
|
||||||
|
# Update album artwork
|
||||||
|
artwork.addArtwork(allart, albumid, "album", kodicursor)
|
||||||
|
|
||||||
|
def updateUserdata(self, item):
|
||||||
|
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||||
|
# Poster with progress bar
|
||||||
|
kodicursor = self.kodicursor
|
||||||
|
emby_db = self.emby_db
|
||||||
|
kodi_db = self.kodi_db
|
||||||
|
API = api.API(item)
|
||||||
|
|
||||||
|
# Get emby information
|
||||||
|
itemid = item['Id']
|
||||||
|
checksum = API.getChecksum()
|
||||||
|
userdata = API.getUserData()
|
||||||
|
runtime = API.getRuntime()
|
||||||
|
rating = userdata['UserRating']
|
||||||
|
|
||||||
|
# Get Kodi information
|
||||||
|
emby_dbitem = emby_db.getItem_byId(itemid)
|
||||||
|
try:
|
||||||
|
kodiid = emby_dbitem[0]
|
||||||
|
mediatype = emby_dbitem[4]
|
||||||
|
self.logMsg("Update playstate for %s: %s" % (mediatype, item['Name']), 1)
|
||||||
|
except TypeError:
|
||||||
|
return
|
||||||
|
|
||||||
|
if mediatype == "song":
|
||||||
|
|
||||||
|
#should we ignore this item ?
|
||||||
|
#happens when userdata updated by ratings method
|
||||||
|
if utils.window("ignore-update-%s" %itemid):
|
||||||
|
utils.window("ignore-update-%s" %itemid,clear=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Process playstates
|
||||||
|
playcount = userdata['PlayCount']
|
||||||
|
dateplayed = userdata['LastPlayedDate']
|
||||||
|
|
||||||
|
#process item ratings
|
||||||
|
rating, comment, hasEmbeddedCover = musicutils.getAdditionalSongTags(itemid, rating, API, kodicursor, emby_db, self.enableimportsongrating, self.enableexportsongrating, self.enableupdatesongrating)
|
||||||
|
|
||||||
|
query = "UPDATE song SET iTimesPlayed = ?, lastplayed = ?, rating = ? WHERE idSong = ?"
|
||||||
|
kodicursor.execute(query, (playcount, dateplayed, rating, kodiid))
|
||||||
|
|
||||||
|
elif mediatype == "album":
|
||||||
|
# Process playstates
|
||||||
|
query = "UPDATE album SET iRating = ? WHERE idAlbum = ?"
|
||||||
|
kodicursor.execute(query, (rating, kodiid))
|
||||||
|
|
||||||
|
emby_db.updateReference(itemid, checksum)
|
||||||
|
|
||||||
def remove(self, itemid):
|
def remove(self, itemid):
|
||||||
# Remove kodiid, fileid, pathid, emby reference
|
# Remove kodiid, fileid, pathid, emby reference
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
|
@ -2295,6 +2392,21 @@ class Music(Items):
|
||||||
if mediatype == "song":
|
if mediatype == "song":
|
||||||
# Delete song
|
# Delete song
|
||||||
self.removeSong(kodiid)
|
self.removeSong(kodiid)
|
||||||
|
# This should only address single song scenario, where server doesn't actually
|
||||||
|
# create an album for the song.
|
||||||
|
customitems = emby_db.getItem_byWildId(itemid)
|
||||||
|
emby_db.removeWildItem(itemid)
|
||||||
|
|
||||||
|
for item in customitems:
|
||||||
|
|
||||||
|
item_kid = item[0]
|
||||||
|
item_mediatype = item[1]
|
||||||
|
|
||||||
|
if item_mediatype == "album":
|
||||||
|
childs = emby_db.getItem_byParentId(item_kid, "song")
|
||||||
|
if not childs:
|
||||||
|
# Delete album
|
||||||
|
self.removeAlbum(item_kid)
|
||||||
|
|
||||||
##### IF ALBUM #####
|
##### IF ALBUM #####
|
||||||
|
|
||||||
|
|
|
@ -1157,6 +1157,7 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addAlbum(self, name, musicbrainz):
|
def addAlbum(self, name, musicbrainz):
|
||||||
|
|
||||||
|
kodiversion = self.kodiversion
|
||||||
cursor = self.cursor
|
cursor = self.cursor
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -1172,14 +1173,24 @@ class Kodidb_Functions():
|
||||||
# Create the album
|
# Create the album
|
||||||
cursor.execute("select coalesce(max(idAlbum),0) from album")
|
cursor.execute("select coalesce(max(idAlbum),0) from album")
|
||||||
albumid = cursor.fetchone()[0] + 1
|
albumid = cursor.fetchone()[0] + 1
|
||||||
query = (
|
if kodiversion in (15, 16, 17):
|
||||||
'''
|
query = (
|
||||||
INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID)
|
'''
|
||||||
|
INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType)
|
||||||
|
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (albumid, name, musicbrainz))
|
cursor.execute(query, (albumid, name, musicbrainz, "album"))
|
||||||
|
else: # Helix
|
||||||
|
query = (
|
||||||
|
'''
|
||||||
|
INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID)
|
||||||
|
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
cursor.execute(query, (albumid, name, musicbrainz))
|
||||||
|
|
||||||
return albumid
|
return albumid
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,19 @@
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import xbmc, xbmcaddon, xbmcvfs
|
|
||||||
import utils
|
import xbmc
|
||||||
|
import xbmcaddon
|
||||||
|
import xbmcvfs
|
||||||
|
|
||||||
from mutagen.flac import FLAC, Picture
|
from mutagen.flac import FLAC, Picture
|
||||||
from mutagen.id3 import ID3
|
from mutagen.id3 import ID3
|
||||||
from mutagen import id3
|
from mutagen import id3
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
|
import read_embyserver as embyserver
|
||||||
|
import utils
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
# Helper for the music library, intended to fix missing song ID3 tags on Emby
|
# Helper for the music library, intended to fix missing song ID3 tags on Emby
|
||||||
|
@ -62,6 +68,9 @@ def getEmbyRatingFromKodiRating(rating):
|
||||||
return(like, favourite, deletelike)
|
return(like, favourite, deletelike)
|
||||||
|
|
||||||
def getAdditionalSongTags(embyid, emby_rating, API, kodicursor, emby_db, enableimportsongrating, enableexportsongrating, enableupdatesongrating):
|
def getAdditionalSongTags(embyid, emby_rating, API, kodicursor, emby_db, enableimportsongrating, enableexportsongrating, enableupdatesongrating):
|
||||||
|
|
||||||
|
emby = embyserver.Read_EmbyServer()
|
||||||
|
|
||||||
previous_values = None
|
previous_values = None
|
||||||
filename = API.getFilePath()
|
filename = API.getFilePath()
|
||||||
rating = 0
|
rating = 0
|
||||||
|
@ -163,7 +172,7 @@ def getAdditionalSongTags(embyid, emby_rating, API, kodicursor, emby_db, enablei
|
||||||
# sync details to emby server. Translation needed between ID3 rating and emby likes/favourites:
|
# sync details to emby server. Translation needed between ID3 rating and emby likes/favourites:
|
||||||
like, favourite, deletelike = getEmbyRatingFromKodiRating(rating)
|
like, favourite, deletelike = getEmbyRatingFromKodiRating(rating)
|
||||||
utils.window("ignore-update-%s" %embyid, "true") #set temp windows prop to ignore the update from webclient update
|
utils.window("ignore-update-%s" %embyid, "true") #set temp windows prop to ignore the update from webclient update
|
||||||
API.updateUserRating(embyid, like, favourite, deletelike)
|
emby.updateUserRating(embyid, like, favourite, deletelike)
|
||||||
|
|
||||||
return (rating, comment, hasEmbeddedCover)
|
return (rating, comment, hasEmbeddedCover)
|
||||||
|
|
||||||
|
|
|
@ -562,4 +562,29 @@ class Read_EmbyServer():
|
||||||
if mediatype:
|
if mediatype:
|
||||||
sorted_items.setdefault(mediatype, []).append(item)
|
sorted_items.setdefault(mediatype, []).append(item)
|
||||||
|
|
||||||
return sorted_items
|
return sorted_items
|
||||||
|
|
||||||
|
def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False):
|
||||||
|
# Updates the user rating to Emby
|
||||||
|
doUtils = self.doUtils
|
||||||
|
|
||||||
|
if favourite:
|
||||||
|
url = "{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid
|
||||||
|
doUtils(url, type="POST")
|
||||||
|
elif favourite == False:
|
||||||
|
url = "{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid
|
||||||
|
doUtils(url, type="DELETE")
|
||||||
|
|
||||||
|
if not deletelike and like:
|
||||||
|
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=true&format=json" % itemid
|
||||||
|
doUtils(url, type="POST")
|
||||||
|
elif not deletelike and like == False:
|
||||||
|
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=false&format=json" % itemid
|
||||||
|
doUtil(url, type="POST")
|
||||||
|
elif deletelike:
|
||||||
|
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?format=json" % itemid
|
||||||
|
doUtils(url, type="DELETE")
|
||||||
|
|
||||||
|
self.logMsg("Update user rating to emby for itemid: %s "
|
||||||
|
"| like: %s | favourite: %s | deletelike: %s"
|
||||||
|
% (itemid, like, favourite, deletelike), 1)
|
|
@ -8,6 +8,7 @@ import json
|
||||||
import pstats
|
import pstats
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import StringIO
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import xml.etree.ElementTree as etree
|
import xml.etree.ElementTree as etree
|
||||||
|
@ -538,44 +539,26 @@ def reset():
|
||||||
line1="Database reset has completed, Kodi will now restart to apply the changes.")
|
line1="Database reset has completed, Kodi will now restart to apply the changes.")
|
||||||
xbmc.executebuiltin('RestartApp')
|
xbmc.executebuiltin('RestartApp')
|
||||||
|
|
||||||
def startProfiling():
|
def profiling(sortby="cumulative"):
|
||||||
|
# Will print results to Kodi log
|
||||||
pr = cProfile.Profile()
|
def decorator(func):
|
||||||
pr.enable()
|
def wrapper(*args, **kwargs):
|
||||||
|
|
||||||
return pr
|
pr = cProfile.Profile()
|
||||||
|
|
||||||
def stopProfiling(pr, profileName):
|
pr.enable()
|
||||||
from datetime import time
|
result = func(*args, **kwargs)
|
||||||
pr.disable()
|
pr.disable()
|
||||||
ps = pstats.Stats(pr)
|
|
||||||
|
|
||||||
profiles = xbmc.translatePath("%sprofiles/"
|
|
||||||
% xbmcaddon.Addon().getAddonInfo('profile')).decode('utf-8')
|
|
||||||
|
|
||||||
if not xbmcvfs.exists(profiles):
|
s = StringIO.StringIO()
|
||||||
# Create the profiles folder
|
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
|
||||||
xbmcvfs.mkdir(profiles)
|
ps.print_stats()
|
||||||
|
logMsg("EMBY Profiling", s.getvalue(), 1)
|
||||||
|
|
||||||
timestamp = time.strftime("%Y-%m-%d %H-%M-%S")
|
return result
|
||||||
profile = "%s%s_profile_(%s).tab" % (profiles, profileName, timestamp)
|
|
||||||
|
return wrapper
|
||||||
f = xbmcvfs.File(profile, 'w')
|
return decorator
|
||||||
f.write("NumbCalls\tTotalTime\tCumulativeTime\tFunctionName\tFileName\r\n")
|
|
||||||
for (key, value) in ps.stats.items():
|
|
||||||
(filename, count, func_name) = key
|
|
||||||
(ccalls, ncalls, total_time, cumulative_time, callers) = value
|
|
||||||
try:
|
|
||||||
f.write(
|
|
||||||
"%s\t%s\t%s\t%s\t%s\r\n"
|
|
||||||
% (ncalls, "{:10.4f}".format(total_time),
|
|
||||||
"{:10.4f}".format(cumulative_time), func_name, filename))
|
|
||||||
except ValueError:
|
|
||||||
f.write(
|
|
||||||
"%s\t%s\t%s\t%s\t%s\r\n"
|
|
||||||
% (ncalls, "{0}".format(total_time),
|
|
||||||
"{0}".format(cumulative_time), func_name, filename))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def convertdate(date):
|
def convertdate(date):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Add table
Reference in a new issue