diff --git a/default.py b/default.py index ad4e532c..3a07760c 100644 --- a/default.py +++ b/default.py @@ -22,6 +22,9 @@ sys.path.append(base_resource) import entrypoint import utils +import PlexAPI +import userclient + ################################################################################################# enableProfiling = False @@ -31,7 +34,7 @@ class Main: # MAIN ENTRY POINT def __init__(self): - + plx = PlexAPI.PlexAPI() # Parse parameters base_url = sys.argv[0] addon_handle = int(sys.argv[1]) @@ -90,6 +93,9 @@ class Main: # Other functions if mode == "settings": xbmc.executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)') + if mode == "switchuser": + xbmc.log('Requesting user switch') + userclient.UserClient().signUserOut() elif mode in ("manualsync", "repair"): if utils.window('emby_dbScan') != "true": import librarysync diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py index a96639f2..a38f49ac 100644 --- a/resources/lib/PlexAPI.py +++ b/resources/lib/PlexAPI.py @@ -100,6 +100,25 @@ class PlexAPI(): className = self.__class__.__name__ utils.logMsg("%s %s" % (self.addonName, className), msg, lvl) + def SetPlexLoginToSettings(self, plexLogin, plexToken): + """ + Saves retrieved Plex username and Plex token to Kodi settings file. + """ + utils.settings('plexLogin', value=plexLogin) + utils.settings('plexToken', value=plexToken) + + def GetPlexLoginFromSettings(self): + """ + Returns (myplexlogin, plexLogin, plexToken) from the Kodi file + settings. Returns empty strings if not found. + + myplexlogin is 'true' if user opted to log into plex.tv + """ + plexLogin = utils.settings('plexLogin') + plexToken = utils.settings('plexToken') + myplexlogin = utils.settings('myplexlogin') + return (myplexlogin, plexLogin, plexToken) + def GetPlexLoginAndPassword(self): """ Signs in to plex.tv. @@ -141,9 +160,7 @@ class PlexAPI(): dialog = xbmcgui.Dialog() dialog.ok(self.addonName, 'Could not sign in user %s' % plexLogin) # Write to Kodi settings file - addon = xbmcaddon.Addon() - addon.setSetting('plexLogin', retrievedPlexLogin) - addon.setSetting('plexToken', authtoken) + self.SetPlexLoginToSettings(retrievedPlexLogin, authtoken) return (retrievedPlexLogin, authtoken) def CheckConnection(self, url, token): @@ -888,8 +905,8 @@ class PlexAPI(): usernumber = len(userlist) usertoken = '' # Plex home not in use: only 1 user returned - trials = 1 - while trials < 4: + trials = 0 + while trials < 3: if usernumber > 1: dialog = xbmcgui.Dialog() user_select = dialog.select(self.addonName + ": Select User", userlist) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index a807954e..d6844776 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -80,7 +80,7 @@ def doMainListing(): # some extra entries for settings and stuff. TODO --> localize the labels addDirectoryItem("Network credentials", "plugin://plugin.video.plexkodiconnect/?mode=passwords", False) addDirectoryItem("Settings", "plugin://plugin.video.plexkodiconnect/?mode=settings", False) - addDirectoryItem("Add user to session", "plugin://plugin.video.plexkodiconnect/?mode=adduser", False) + addDirectoryItem("Switch Plex user", "plugin://plugin.video.plexkodiconnect/?mode=switchuser", False) #addDirectoryItem("Cache all images to Kodi texture cache (advanced)", "plugin://plugin.video.plexkodiconnect/?mode=texturecache") addDirectoryItem( label="Refresh Emby playlists", diff --git a/resources/lib/initialsetup.py b/resources/lib/initialsetup.py index 17b2f71c..8bf899f7 100644 --- a/resources/lib/initialsetup.py +++ b/resources/lib/initialsetup.py @@ -39,18 +39,6 @@ class InitialSetup(): className = self.__class__.__name__ utils.logMsg("%s %s" % (self.addonName, className), msg, lvl) - def GetPlexLogin(self): - """ - Returns (myplexlogin, plexLogin, plexToken) from the Kodi file - settings. Returns empty strings if not found. - - myplexlogin is 'true' if user opted to log into plex.tv - """ - plexLogin = utils.settings('plexLogin') - plexToken = utils.settings('plexToken') - myplexlogin = utils.settings('myplexlogin') - return (myplexlogin, plexLogin, plexToken) - def setup(self): # Check server, user, direct paths, music, direct stream if not direct path. string = self.__language__ @@ -62,7 +50,7 @@ class InitialSetup(): server = self.userClient.getServer() clientId = self.clientInfo.getDeviceId() serverid = self.userClient.getServerId() - myplexlogin, plexLogin, plexToken = self.GetPlexLogin() + myplexlogin, plexLogin, plexToken = self.plx.GetPlexLoginFromSettings() # Optionally sign into plex.tv. Will not be called on very first run if plexToken and myplexlogin == 'true': diff --git a/resources/lib/userclient.py b/resources/lib/userclient.py index 6865330b..8911626c 100644 --- a/resources/lib/userclient.py +++ b/resources/lib/userclient.py @@ -46,9 +46,17 @@ class UserClient(threading.Thread): self.addonName = clientinfo.ClientInfo().getAddonName() self.doUtils = downloadutils.DownloadUtils() - + + self.signoutUser = threading.Event() + threading.Thread.__init__(self) + def signUserOut(self): + self.signoutUser.set() + + def userSignedOut(self): + return self.signoutUser.isSet() + def logMsg(self, msg, lvl=1): className = self.__class__.__name__ @@ -307,18 +315,14 @@ class UserClient(threading.Thread): ##### AUTHENTICATE USER ##### # Choose Plex user login - try: - username, userId, accessToken = PlexAPI.PlexAPI().ChoosePlexHomeUser() - except (KeyError, TypeError): - self.logMsg("Failed to retrieve the api key.", 1) - accessToken = None + username, userId, accessToken = PlexAPI.PlexAPI().ChoosePlexHomeUser() - if accessToken is not None: + if accessToken is not "": self.currUser = username xbmcgui.Dialog().notification("Emby server", "Welcome %s!" % username) utils.settings('accessToken', value=accessToken) utils.settings('userId%s' % username, value=userId) - self.logMsg("User Authenticated: %s" % accessToken, 1) + self.logMsg("User authenticated with an access token", 1) self.loadCurrUser(authenticated=True) utils.window('emby_serverStatus', clear=True) self.retry = 0 @@ -326,37 +330,22 @@ class UserClient(threading.Thread): self.logMsg("User authentication failed.", 1) utils.settings('accessToken', value="") utils.settings('userId%s' % username, value="") - xbmcgui.Dialog().ok("Error connecting", "Invalid username or password.") - - # Give two attempts at entering password - if self.retry == 2: - self.logMsg( - """Too many retries. You can retry by resetting - attempts in the addon settings.""", 1) - utils.window('emby_serverStatus', value="Stop") - xbmcgui.Dialog().ok( - heading="Error connecting", - line1="Failed to authenticate too many times.", - line2="You can retry by resetting attempts in the addon settings.") - - self.retry += 1 + self.retry = 0 self.auth = False def resetClient(self): self.logMsg("Reset UserClient authentication.", 1) username = self.getUsername() - - if self.currToken is not None: - # In case of 401, removed saved token - utils.settings('accessToken', value="") - utils.window('emby_accessToken%s' % username, clear=True) - self.currToken = None - self.logMsg("User token has been removed.", 1) - + + utils.settings('accessToken', value="") + utils.window('emby_accessToken%s' % username, clear=True) + self.currToken = None + self.logMsg("User token has been removed.", 1) + self.auth = True self.currUser = None - + def run(self): monitor = xbmc.Monitor() @@ -376,6 +365,13 @@ class UserClient(threading.Thread): utils.window('emby_serverStatus', value="Auth") self.resetClient() + if self.userSignedOut(): + # Check whether another thread wanted to sign out user + self.logMsg("User sign out requested", 0) + self.resetClient() + # Reset threading event + self.signoutUser.clear() + if self.auth and (self.currUser is None): # Try to authenticate user status = utils.window('emby_serverStatus')