From 11e4a70e25fca62ccdf757d9da75d3f79d41281e Mon Sep 17 00:00:00 2001
From: angelblue05 <tamara.angel05@gmail.com>
Date: Wed, 13 May 2015 23:48:35 -0500
Subject: [PATCH] Reworked the userclient with possibilities

Revoked token was actually broken, handle access schedule better,
restart/start properly. This is to stabilize things.
---
 resources/lib/DownloadUtils.py   | 15 ++++++-----
 resources/lib/UserClient.py      | 45 +++++++++++++++++++++++---------
 resources/lib/WebSocketClient.py |  7 ++++-
 service.py                       |  5 +++-
 4 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/resources/lib/DownloadUtils.py b/resources/lib/DownloadUtils.py
index ba06efb4..dabef416 100644
--- a/resources/lib/DownloadUtils.py
+++ b/resources/lib/DownloadUtils.py
@@ -124,7 +124,6 @@ class DownloadUtils():
         self.s.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
 
         self.logMsg("Requests session started on: %s" % self.server)
-        self.postCapabilities(self.deviceId)
 
     def imageUrl(self, id, type, index, width, height):
         # To move to API.py
@@ -279,13 +278,14 @@ class DownloadUtils():
                 # Unauthorized
                 status = WINDOW.getProperty("Server_status")
 
-                if r.headers['X-Application-Error-Code'] == "ParentalControl":
-                    # Parental control - access restricted
-                    WINDOW.setProperty("Server_status", "restricted")
-                    xbmcgui.Dialog().notification("Emby server", "Access restricted.", xbmcgui.NOTIFICATION_ERROR, time=5000)
-                    return False
+                if 'x-application-error-code' in r.headers:
+                    if r.headers['X-Application-Error-Code'] == "ParentalControl":
+                        # Parental control - access restricted
+                        WINDOW.setProperty("Server_status", "restricted")
+                        xbmcgui.Dialog().notification("Emby server", "Access restricted.", xbmcgui.NOTIFICATION_ERROR, time=5000)
+                        return False
 
-                elif (status == "401") or (status == "Auth"):
+                if (status == "401") or (status == "Auth"):
                     pass
 
                 else:
@@ -293,6 +293,7 @@ class DownloadUtils():
                     WINDOW.setProperty("Server_status", "401")
                     self.logMsg("HTTP Error: %s" % e, 0)
                     xbmcgui.Dialog().notification("Error connecting", "Unauthorized.", xbmcgui.NOTIFICATION_ERROR)
+                    return 401
 
             elif (r.status_code == 301) or (r.status_code == 302):
                 # Redirects
diff --git a/resources/lib/UserClient.py b/resources/lib/UserClient.py
index bb0f166a..0ce3c4bf 100644
--- a/resources/lib/UserClient.py
+++ b/resources/lib/UserClient.py
@@ -178,6 +178,9 @@ class UserClient(threading.Thread):
             self.logMsg("Access is restricted.")
             self.HasAccess = False
             return
+        elif self.WINDOW.getProperty('Server_online') != "true":
+            # Server connection failed
+            return
 
         if self.WINDOW.getProperty("Server_status") == "restricted":
             self.logMsg("Access is granted.")
@@ -186,7 +189,7 @@ class UserClient(threading.Thread):
             xbmcgui.Dialog().notification("Emby server", "Access is enabled.")
         return
 
-    def loadCurrUser(self):
+    def loadCurrUser(self, authenticated=False):
 
         WINDOW = self.WINDOW
         doUtils = self.doUtils
@@ -199,6 +202,17 @@ class UserClient(threading.Thread):
         self.ssl = self.getSSLverify()
         self.sslcert = self.getSSL()
 
+        # Test the validity of current token
+        if authenticated == False:
+            url = "%s/mediabrowser/Users/%s" % (self.currServer, self.currUserId)
+            WINDOW.setProperty("currUser", username)
+            WINDOW.setProperty("accessToken%s" % username, self.currToken)
+            result = doUtils.downloadUrl(url, type="POST")
+            if result == 401:
+                # Token is no longer valid
+                self.resetClient()
+                return False
+
         # Set to windows property
         WINDOW.setProperty("currUser", username)
         WINDOW.setProperty("accessToken%s" % username, self.currToken)
@@ -212,6 +226,8 @@ class UserClient(threading.Thread):
         doUtils.setServer(self.currServer)
         doUtils.setToken(self.currToken)
         doUtils.setSSL(self.ssl, self.sslcert)
+        # parental control - let's verify if access is restricted
+        self.hasAccess()
         # Start DownloadUtils session
         doUtils.startSession()
 
@@ -239,13 +255,15 @@ class UserClient(threading.Thread):
             return
         # If there's a token
         if (self.getToken() != ""):
-            self.loadCurrUser()
-            self.logMsg("Current user: %s" % self.currUser, 0)
-            self.logMsg("Current userId: %s" % self.currUserId, 0)
-            self.logMsg("Current accessToken: %s" % self.currToken, 0)
-            # parental control - let's verify if access is restricted
-            self.hasAccess()
-            return
+            result = self.loadCurrUser()
+
+            if result == False:
+                pass
+            else:
+                self.logMsg("Current user: %s" % self.currUser, 0)
+                self.logMsg("Current userId: %s" % self.currUserId, 0)
+                self.logMsg("Current accessToken: %s" % self.currToken, 0)
+                return
         
         users = self.getPublicUsers()
         password = ""
@@ -292,11 +310,12 @@ class UserClient(threading.Thread):
 
         if (result != None and accessToken != None):
             self.currUser = username
+            xbmcgui.Dialog().notification("Emby server", "Welcome %s!" % self.currUser)
             userId = result[u'User'][u'Id']
             addon.setSetting("accessToken", accessToken)
             addon.setSetting("userId%s" % username, userId)
             self.logMsg("User Authenticated: %s" % accessToken)
-            self.loadCurrUser()
+            self.loadCurrUser(authenticated=True)
             self.WINDOW.setProperty("Server_status", "")
             self.retry = 0
             return
@@ -318,17 +337,19 @@ class UserClient(threading.Thread):
 
     def resetClient(self):
 
+        username = self.getUsername()
+        self.logMsg("Reset UserClient authentication.", 1)
         if (self.currToken != None):
             # In case of 401, removed saved token
-            self.addon.setSetting("accessToken%s" % self.currUser, "")
-            self.WINDOW.setProperty("accessToken%s" % self.currUser, "")
+            self.addon.setSetting("accessToken", "")
+            self.WINDOW.setProperty("accessToken%s" % username, "")
             self.currToken = None
             self.logMsg("User token has been removed.", 1)
         
         self.auth = True
         self.currUser = None
         return
-
+        
 
     def run(self):
 
diff --git a/resources/lib/WebSocketClient.py b/resources/lib/WebSocketClient.py
index a1c52d2a..1aeff13e 100644
--- a/resources/lib/WebSocketClient.py
+++ b/resources/lib/WebSocketClient.py
@@ -28,6 +28,7 @@ class WebSocketThread(threading.Thread):
 
     _shared_state = {}
 
+    doUtils = DownloadUtils()
     clientInfo = ClientInformation()
     KodiMonitor = KodiMonitor.Kodi_Monitor()
     addonName = clientInfo.getAddonName()
@@ -258,10 +259,14 @@ class WebSocketThread(threading.Thread):
                                     on_close = self.on_close)
                                     
         self.client.on_open = self.on_open
+        self.doUtils.postCapabilities(deviceId)
         
         while not self.KodiMonitor.abortRequested():
             
-            self.client.run_forever()
+            if WINDOW.getProperty("Server_online") == "true":
+                # Server came back online, repost capabilities
+                self.doUtils.postCapabilities(deviceId)
+                self.client.run_forever()
 
             if (self.keepRunning):
                 # Server is not online
diff --git a/service.py b/service.py
index cff38680..206ece22 100644
--- a/service.py
+++ b/service.py
@@ -143,7 +143,6 @@ class Service():
                             if self.KodiMonitor.waitForAbort(1):
                                 # Abort was requested while waiting. We should exit
                                 break    
-                            #WebSocketThread().processPendingActions()
                 else:
                     
                     if self.warn_auth:
@@ -155,6 +154,10 @@ class Service():
                         WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
                         user.hasAccess()
 
+                        if WINDOW.getProperty('Server_online') != "true":
+                            # Server went offline
+                            break
+
                         if self.KodiMonitor.waitForAbort(5):
                             # Abort was requested while waiting. We should exit
                             break