From e1dca1509a5a6a934f78fad70a8cf36c2921a88b Mon Sep 17 00:00:00 2001 From: JonnyWong16 Date: Tue, 13 Feb 2018 10:49:11 -0800 Subject: [PATCH] Reconnect Plex Cloud without keeping the server awake --- plexpy/__init__.py | 21 ++++++++++++++------- plexpy/activity_pinger.py | 15 ++++++++++++++- plexpy/http_handler.py | 12 +++++++++--- plexpy/plextv.py | 35 +++++++++++++++++++++++++++-------- plexpy/pmsconnect.py | 2 +- plexpy/web_socket.py | 20 ++++++++++++-------- 6 files changed, 77 insertions(+), 28 deletions(-) diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 998a4420..728be8d3 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -397,8 +397,12 @@ def initialize_scheduler(): schedule_job(libraries.refresh_libraries, 'Refresh libraries list', hours=library_hours, minutes=0, seconds=0) - schedule_job(activity_pinger.check_server_response, 'Check for server response', - hours=0, minutes=0, seconds=0) + if plexpy.CONFIG.PMS_IS_CLOUD: + schedule_job(activity_pinger.check_cloud_status, 'Check for server response', + hours=0, minutes=0, seconds=0) + else: + schedule_job(activity_pinger.check_server_response, 'Check for server response', + hours=0, minutes=0, seconds=0) else: # Cancel all jobs @@ -415,12 +419,15 @@ def initialize_scheduler(): schedule_job(libraries.refresh_libraries, 'Refresh libraries list', hours=0, minutes=0, seconds=0) - # Schedule job to reconnect websocket - response_seconds = CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS * CONFIG.WEBSOCKET_CONNECTION_TIMEOUT - response_seconds = 60 if response_seconds < 60 else response_seconds + if plexpy.CONFIG.PMS_IS_CLOUD: + # Schedule job to check for cloud server status + schedule_job(activity_pinger.check_cloud_status, 'Check for server response', + hours=0, minutes=0, seconds=60) - schedule_job(activity_pinger.check_server_response, 'Check for server response', - hours=0, minutes=0, seconds=response_seconds) + else: + # Schedule job to reconnect websocket + schedule_job(activity_pinger.check_server_response, 'Check for server response', + hours=0, minutes=0, seconds=60) # Start scheduler if start_jobs and len(SCHED.get_jobs()): diff --git a/plexpy/activity_pinger.py b/plexpy/activity_pinger.py index 158461e0..abcda1b9 100644 --- a/plexpy/activity_pinger.py +++ b/plexpy/activity_pinger.py @@ -325,4 +325,17 @@ def check_server_updates(): plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_pmsupdate', 'pms_download_info': download_info}) else: - logger.info(u"Tautulli Monitor :: No PMS update available.") \ No newline at end of file + logger.info(u"Tautulli Monitor :: No PMS update available.") + + +def check_cloud_status(): + logger.info(u"Tautulli Monitor :: Checking for Plex Cloud server status...") + + plex_tv = plextv.PlexTV() + cloud_status = plex_tv.get_cloud_server_status() + + if cloud_status: + logger.info(u"Tautulli Monitor :: Plex Cloud server is active.") + check_server_response() + else: + logger.info(u"Tautulli Monitor :: Plex Cloud server is sleeping.") diff --git a/plexpy/http_handler.py b/plexpy/http_handler.py index e0bd9ccf..189548e5 100644 --- a/plexpy/http_handler.py +++ b/plexpy/http_handler.py @@ -39,11 +39,17 @@ class HTTPHandler(object): else: self.urls = urls + self.headers = {'X-Plex-Device-Name': 'Tautulli', + 'X-Plex-Product': 'Tautulli', + 'X-Plex-Version': plexpy.common.VERSION_NUMBER, + 'X-Plex-Platform': plexpy.common.PLATFORM, + 'X-Plex-Platform-Version': plexpy.common.PLATFORM_VERSION, + 'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID, + } + self.token = token if self.token: - self.headers = {'X-Plex-Token': self.token} - else: - self.headers = {} + self.headers['X-Plex-Token'] = self.token self.timeout = timeout self.ssl_verify = ssl_verify diff --git a/plexpy/plextv.py b/plexpy/plextv.py index 5f2b2238..f701c26d 100644 --- a/plexpy/plextv.py +++ b/plexpy/plextv.py @@ -144,14 +144,7 @@ class PlexTV(object): uri = '/users/sign_in.xml' base64string = base64.b64encode(('%s:%s' % (self.username, self.password)).encode('utf-8')) headers = {'Content-Type': 'application/xml; charset=utf-8', - 'X-Plex-Device-Name': 'Tautulli', - 'X-Plex-Product': 'Tautulli', - 'X-Plex-Version': plexpy.common.VERSION_NUMBER, - 'X-Plex-Platform': plexpy.common.PLATFORM, - 'X-Plex-Platform-Version': plexpy.common.PLATFORM_VERSION, - 'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID, - 'Authorization': 'Basic %s' % base64string - } + 'Authorization': 'Basic %s' % base64string} request = self.request_handler.make_request(uri=uri, request_type='POST', @@ -318,6 +311,14 @@ class PlexTV(object): return request + def cloud_server_status(self, output_format=''): + uri = '/api/v2/cloud_server' + request = self.request_handler.make_request(uri=uri, + request_type='GET', + output_format=output_format) + + return request + def get_full_users_list(self): friends_list = self.get_plextv_friends(output_format='xml') own_account = self.get_plextv_user_details(output_format='xml') @@ -753,3 +754,21 @@ class PlexTV(object): devices_list.append(device) return devices_list + + def get_cloud_server_status(self): + cloud_status = self.cloud_server_status(output_format='xml') + + try: + status_info = cloud_status.getElementsByTagName('info') + except Exception as e: + logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s." % e) + return False + + for info in status_info: + servers = info.getElementsByTagName('server') + for s in servers: + if helpers.get_xml_attr(s, 'address') == plexpy.CONFIG.PMS_IP: + if helpers.get_xml_attr(info, 'running') == '1': + return True + else: + return False diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 5f23a7a0..b0551108 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -61,7 +61,7 @@ class PmsConnect(object): self.url = plexpy.CONFIG.PMS_URL elif not self.url: self.url = 'http://{hostname}:{port}'.format(hostname=plexpy.CONFIG.PMS_IP, - port=plexpy.CONFIG.PMS_PORT) + port=plexpy.CONFIG.PMS_PORT) self.timeout = plexpy.CONFIG.PMS_TIMEOUT if not self.token: diff --git a/plexpy/web_socket.py b/plexpy/web_socket.py index bdc2e13b..775d78c4 100644 --- a/plexpy/web_socket.py +++ b/plexpy/web_socket.py @@ -41,23 +41,23 @@ def start_thread(): def on_connect(): - plexpy.initialize_scheduler() - if not plexpy.PLEX_SERVER_UP: logger.info(u"Tautulli WebSocket :: The Plex Media Server is back up.") plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intup'}) plexpy.PLEX_SERVER_UP = True - -def on_disconnect(ws_exception=False): - activity_processor.ActivityProcessor().set_temp_stopped() plexpy.initialize_scheduler() + +def on_disconnect(ws_exception=False): if not ws_exception and plexpy.PLEX_SERVER_UP: - logger.info(u"Tautulli WebSocket :: Unable to get an internal response from the server, Plex server is down.") + logger.info(u"Tautulli WebSocket :: Unable to get a response from the server, Plex server is down.") plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intdown'}) plexpy.PLEX_SERVER_UP = False + activity_processor.ActivityProcessor().set_temp_stopped() + plexpy.initialize_scheduler() + def reconnect(): global ws_reconnect @@ -89,7 +89,7 @@ def run(): ws_exception = False # Try an open the websocket connection - while not plexpy.WS_CONNECTED and reconnects <= plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: + while not plexpy.WS_CONNECTED and reconnects < plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: reconnects += 1 # Sleep 5 between connection attempts @@ -116,7 +116,11 @@ def run(): reconnects = 0 except websocket.WebSocketConnectionClosedException: - if reconnects <= plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: + if plexpy.CONFIG.PMS_IS_CLOUD: + logger.warn(u"Tautulli WebSocket :: Connection has closed.") + activity_pinger.check_cloud_status() + + if not plexpy.CONFIG.PMS_IS_CLOUD and reconnects < plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: reconnects += 1 # Sleep 5 between connection attempts