From e411da027ece1215da8c82ccefaf8f8489e6dc66 Mon Sep 17 00:00:00 2001
From: angelblue05 <angelblue.dev@gmail.com>
Date: Tue, 22 Jan 2019 21:35:54 -0600
Subject: [PATCH] Adjust client api

---
 resources/lib/emby/client.py   |   6 +-
 resources/lib/emby/core/api.py | 499 +++++++++++++++++----------------
 2 files changed, 254 insertions(+), 251 deletions(-)

diff --git a/resources/lib/emby/client.py b/resources/lib/emby/client.py
index f5a2847c..d78fc07d 100644
--- a/resources/lib/emby/client.py
+++ b/resources/lib/emby/client.py
@@ -17,6 +17,7 @@ LOG = logging.getLogger('Emby.'+__name__)
 #################################################################################################
 
 def callback(message, data):
+
     ''' Callback function should received message, data            
         message: string
         data: json dictionary
@@ -35,8 +36,7 @@ class EmbyClient(object):
         self.http = HTTP(self)
         self.wsc = WSClient(self)
         self.auth = ConnectionManager(self)
-        self.emby = api
-        self.emby.client = self.http
+        self.emby = api.API(self.http)
         self.callback_ws = callback
         self.callback = callback
 
@@ -100,8 +100,6 @@ class EmbyClient(object):
             return self.auth.__shortcuts__(key.replace('auth/', "", 1))
 
         elif key.startswith('api'):
-            self.emby.client = self.http # Since api is not a class, re-assign global var to correct http adapter
-
             return self.emby
 
         elif key == 'connected':
diff --git a/resources/lib/emby/core/api.py b/resources/lib/emby/core/api.py
index 8a537953..7dbdc19a 100644
--- a/resources/lib/emby/core/api.py
+++ b/resources/lib/emby/core/api.py
@@ -2,25 +2,7 @@
 
 #################################################################################################
 
-client = None
-
-#################################################################################################
-
-def _http(action, url, request={}):
-    request.update({'type': action, 'handler': url})
-
-    return  client.request(request)
-
-def _get(handler, params=None):
-    return  _http("GET", handler, {'params': params})
-
-def _post(handler, json=None, params=None):
-    return  _http("POST", handler, {'params': params, 'json': json})
-
-def _delete(handler, params=None):
-    return  _http("DELETE", handler, {'params': params})
-
-def emby_url(handler):
+def emby_url(client, handler):
     return  "%s/emby/%s" % (client.config['auth.server'], handler)
 
 def basic_info():
@@ -45,295 +27,318 @@ def music_info():
 
 #################################################################################################
 
-# Bigger section of the Emby api
+class API(object):
 
-#################################################################################################
+    ''' All the api calls to the server.
+    '''
+    def __init__(self, client, *args, **kwargs):
+        self.client = client
 
-def try_server():
-    return  _get("System/Info/Public")
+    def _http(self, action, url, request={}):
+        request.update({'type': action, 'handler': url})
 
-def sessions(handler="", action="GET", params=None, json=None):
+        return  self.client.request(request)
 
-    if action == "POST":
-        return  _post("Sessions%s" % handler, json, params)
-    elif action == "DELETE":
-        return  _delete("Sessions%s" % handler, params)
-    else:
-        return  _get("Sessions%s" % handler, params)
+    def _get(self, handler, params=None):
+        return  self._http("GET", handler, {'params': params})
 
-def users(handler="", action="GET", params=None, json=None):
+    def _post(self, handler, json=None, params=None):
+        return  self._http("POST", handler, {'params': params, 'json': json})
 
-    if action == "POST":
-        return  _post("Users/{UserId}%s" % handler, json, params)
-    elif action == "DELETE":
-        return  _delete("Users/{UserId}%s" % handler, params)
-    else:
-        return  _get("Users/{UserId}%s" % handler, params)
+    def _delete(self, handler, params=None):
+        return  self._http("DELETE", handler, {'params': params})
 
-def items(handler="", action="GET", params=None, json=None):
-    
-    if action == "POST":
-        return  _post("Items%s" % handler, json, params)
-    elif action == "DELETE":
-        return  _delete("Items%s" % handler, params)
-    else:
-        return  _get("Items%s" % handler, params)
+    #################################################################################################
 
-def user_items(handler="", params=None):
-    return  users("/Items%s" % handler, params=params)
+    # Bigger section of the Emby api
 
-def shows(handler, params):
-    return  _get("Shows%s" % handler, params)
+    #################################################################################################
 
-def videos(handler):
-    return  _get("Videos%s" % handler)
+    def try_server(self):
+        return  self._get("System/Info/Public")
 
-def artwork(item_id, art, max_width, ext="jpg", index=None):
+    def sessions(self, handler="", action="GET", params=None, json=None):
 
-    if index is None:
-        return  emby_url("Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext))
+        if action == "POST":
+            return  self._post("Sessions%s" % handler, json, params)
+        elif action == "DELETE":
+            return  self._delete("Sessions%s" % handler, params)
+        else:
+            return  self._get("Sessions%s" % handler, params)
 
-    return emby_url("Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext))
+    def users(self, handler="", action="GET", params=None, json=None):
 
-#################################################################################################
+        if action == "POST":
+            return  self._post("Users/{UserId}%s" % handler, json, params)
+        elif action == "DELETE":
+            return  self._delete("Users/{UserId}%s" % handler, params)
+        else:
+            return  self._get("Users/{UserId}%s" % handler, params)
 
-# More granular api
+    def items(self, handler="", action="GET", params=None, json=None):
+        
+        if action == "POST":
+            return  self._post("Items%s" % handler, json, params)
+        elif action == "DELETE":
+            return  self._delete("Items%s" % handler, params)
+        else:
+            return  self._get("Items%s" % handler, params)
 
-#################################################################################################
+    def user_items(self, handler="", params=None):
+        return  self.users("/Items%s" % handler, params=params)
 
-def get_users():
-    return  _get("Users")
+    def shows(self, handler, params):
+        return  self._get("Shows%s" % handler, params)
 
-def get_public_users():
-    return  _get("Users/Public")
+    def videos(self, handler):
+        return  self._get("Videos%s" % handler)
 
-def get_user(user_id=None):
-    return  users() if user_id is None else _get("Users/%s" % user_id)
+    def artwork(self, item_id, art, max_width, ext="jpg", index=None):
 
-def get_views():
-    return  users("/Views")
+        if index is None:
+            return  emby_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext))
 
-def get_media_folders():
-    return  users("/Items")
+        return emby_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext))
 
-def get_item(item_id):
-    return  users("/Items/%s" % item_id)
+    #################################################################################################
 
-def get_items(item_ids):
-    return  users("/Items", params={
-                'Ids': ','.join(str(x) for x in item_ids),
-                'Fields': info()
-            })
+    # More granular api
 
-def get_sessions():
-    return  sessions(params={'ControllableByUserId': "{UserId}"})
+    #################################################################################################
 
-def get_device(device_id):
-    return  sessions(params={'DeviceId': device_id})
+    def get_users(self):
+        return  self._get("Users")
 
-def post_session(session_id, url, params=None, data=None):
-    return  sessions("/%s/%s" % (session_id, url), "POST", params, data)
+    def get_public_users(self):
+        return  self._get("Users/Public")
 
-def get_images(item_id):
-    return  items("/%s/Images" % item_id)
+    def get_user(self, user_id=None):
+        return  self.users() if user_id is None else self._get("Users/%s" % user_id)
 
-def get_suggestion(media="Movie,Episode", limit=1):
-    return  users("/Suggestions", {
-                'Type': media,
-                'Limit': limit
-            })
+    def get_views(self):
+        return  self.users("/Views")
 
-def get_recently_added(media=None, parent_id=None, limit=20):
-    return  user_items("/Latest", {
-                'Limit': limit,
-                'UserId': "{UserId}",
-                'IncludeItemTypes': media,
-                'ParentId': parent_id,
-                'Fields': info()
-            })
+    def get_media_folders(self):
+        return  self.users("/Items")
 
-def get_next(index=None, limit=1):
-    return  shows("/NextUp", {
-                'Limit': limit,
-                'UserId': "{UserId}",
-                'StartIndex': None if index is None else int(index)
-            })
+    def get_item(self, item_id):
+        return  self.users("/Items/%s" % item_id)
 
-def get_adjacent_episodes(show_id, item_id):
-    return  shows("/%s/Episodes" % show_id, {
-                'UserId': "{UserId}",
-                'AdjacentTo': item_id,
-                'Fields': "Overview"
-            })
+    def get_items(self, item_ids):
+        return  self.users("/Items", params={
+                    'Ids': ','.join(str(x) for x in item_ids),
+                    'Fields': info()
+                })
 
-def get_genres(parent_id=None):
-    return  _get("Genres", {
-                'ParentId': parent_id,
-                'UserId': "{UserId}",
-                'Fields': info()
-            })
+    def get_sessions(self):
+        return  self.sessions(params={'ControllableByUserId': "{UserId}"})
 
-def get_recommendation(parent_id=None, limit=20):
-    return  _get("Movies/Recommendations", {
-                'ParentId': parent_id,
-                'UserId': "{UserId}",
-                'Fields': info(),
-                'Limit': limit
-            })
+    def get_device(self, device_id):
+        return  self.sessions(params={'DeviceId': device_id})
 
-def get_items_by_letter(parent_id=None, media=None, letter=None):
-    return  user_items(params={
-                'ParentId': parent_id,
-                'NameStartsWith': letter,
-                'Fields': info(),
-                'Recursive': True,
-                'IncludeItemTypes': media
-            })
+    def post_session(self, session_id, url, params=None, data=None):
+        return  self.sessions("/%s/%s" % (session_id, url), "POST", params, data)
 
-def get_channels():
-    return  _get("LiveTv/Channels", {
-                'UserId': "{UserId}",
-                'EnableImages': True,
-                'EnableUserData': True
-            })
+    def get_images(self, item_id):
+        return  self.items("/%s/Images" % item_id)
 
-def get_intros(item_id):
-    return  user_items("/%s/Intros" % item_id)
+    def get_suggestion(self, media="Movie,Episode", limit=1):
+        return  self.users("/Suggestions", {
+                    'Type': media,
+                    'Limit': limit
+                })
 
-def get_additional_parts(item_id):
-    return  videos("/%s/AdditionalParts" % item_id)
+    def get_recently_added(self, media=None, parent_id=None, limit=20):
+        return  self.user_items("/Latest", {
+                    'Limit': limit,
+                    'UserId': "{UserId}",
+                    'IncludeItemTypes': media,
+                    'ParentId': parent_id,
+                    'Fields': info()
+                })
 
-def delete_item(item_id):
-    return  items("/%s" % item_id, "DELETE")
+    def get_next(self, index=None, limit=1):
+        return  self.shows("/NextUp", {
+                    'Limit': limit,
+                    'UserId': "{UserId}",
+                    'StartIndex': None if index is None else int(index)
+                })
 
-def get_local_trailers(item_id):
-    return  user_items("/%s/LocalTrailers" % item_id)
+    def get_adjacent_episodes(self, show_id, item_id):
+        return  self.shows("/%s/Episodes" % show_id, {
+                    'UserId': "{UserId}",
+                    'AdjacentTo': item_id,
+                    'Fields': "Overview"
+                })
 
-def get_transcode_settings():
-    return  _get('System/Configuration/encoding')
+    def get_genres(self, parent_id=None):
+        return  self._get("Genres", {
+                    'ParentId': parent_id,
+                    'UserId': "{UserId}",
+                    'Fields': info()
+                })
 
-def get_ancestors(item_id):
-    return  items("/%s/Ancestors" % item_id, params={
-                'UserId': "{UserId}"
-            })
+    def get_recommendation(self, parent_id=None, limit=20):
+        return  self._get("Movies/Recommendations", {
+                    'ParentId': parent_id,
+                    'UserId': "{UserId}",
+                    'Fields': info(),
+                    'Limit': limit
+                })
 
-def get_items_theme_video(parent_id):
-    return  users("/Items", params={
-                'HasThemeVideo': True,
-                'ParentId': parent_id
-            })
+    def get_items_by_letter(self, parent_id=None, media=None, letter=None):
+        return  self.user_items(params={
+                    'ParentId': parent_id,
+                    'NameStartsWith': letter,
+                    'Fields': info(),
+                    'Recursive': True,
+                    'IncludeItemTypes': media
+                })
 
-def get_themes(item_id):
-    return  items("/%s/ThemeMedia" % item_id, params={
-                'UserId': "{UserId}",
-                'InheritFromParent': True
-            })
+    def get_channels(self):
+        return  self._get("LiveTv/Channels", {
+                    'UserId': "{UserId}",
+                    'EnableImages': True,
+                    'EnableUserData': True
+                })
 
-def get_items_theme_song(parent_id):
-    return  users("/Items", params={
-                'HasThemeSong': True,
-                'ParentId': parent_id
-            })
+    def get_intros(self, item_id):
+        return  self.user_items("/%s/Intros" % item_id)
 
-def get_plugins():
-    return  _get("Plugins")
+    def get_additional_parts(self, item_id):
+        return  self.videos("/%s/AdditionalParts" % item_id)
 
-def get_seasons(show_id):
-    return  shows("/%s/Seasons" % show_id, params={
-                'UserId': "{UserId}",
-                'EnableImages': True,
-                'Fields': info()
-            })
+    def delete_item(self, item_id):
+        return  self.items("/%s" % item_id, "DELETE")
 
-def get_date_modified(date, parent_id, media=None):
-    return  users("/Items", params={
-                'ParentId': parent_id,
-                'Recursive': False,
-                'IsMissing': False,
-                'IsVirtualUnaired': False,
-                'IncludeItemTypes': media or None,
-                'MinDateLastSaved': date,
-                'Fields': info()
-            })
+    def get_local_trailers(self, item_id):
+        return  self.user_items("/%s/LocalTrailers" % item_id)
 
-def get_userdata_date_modified(date, parent_id, media=None):
-    return  users("/Items", params={
-                'ParentId': parent_id,
-                'Recursive': True,
-                'IsMissing': False,
-                'IsVirtualUnaired': False,
-                'IncludeItemTypes': media or None,
-                'MinDateLastSavedForUser': date,
-                'Fields': info()
-            })
+    def get_transcode_settings(self):
+        return  self._get('System/Configuration/encoding')
 
-def refresh_item(item_id):
-    return  items("/%s/Refresh" % item_id, "POST", json={
-                'Recursive': True,
-                'ImageRefreshMode': "FullRefresh",
-                'MetadataRefreshMode': "FullRefresh",
-                'ReplaceAllImages': False,
-                'ReplaceAllMetadata': True
-            })
+    def get_ancestors(self, item_id):
+        return  self.items("/%s/Ancestors" % item_id, params={
+                    'UserId': "{UserId}"
+                })
 
-def favorite(item_id, option=True):
-    return  users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE")
+    def get_items_theme_video(self, parent_id):
+        return  self.users("/Items", params={
+                    'HasThemeVideo': True,
+                    'ParentId': parent_id
+                })
 
-def get_system_info():
-    return  _get("System/Configuration")
+    def get_themes(self, item_id):
+        return  self.items("/%s/ThemeMedia" % item_id, params={
+                    'UserId': "{UserId}",
+                    'InheritFromParent': True
+                })
 
-def post_capabilities(data):
-    return  sessions("/Capabilities/Full", "POST", json=data)
+    def get_items_theme_song(self, parent_id):
+        return  self.users("/Items", params={
+                    'HasThemeSong': True,
+                    'ParentId': parent_id
+                })
 
-def session_add_user(session_id, user_id, option=True):
-    return  sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE")
+    def get_plugins(self):
+        return  self._get("Plugins")
 
-def session_playing(data):
-    return  sessions("/Playing", "POST", json=data)
+    def get_seasons(self, show_id):
+        return  self.shows("/%s/Seasons" % show_id, params={
+                    'UserId': "{UserId}",
+                    'EnableImages': True,
+                    'Fields': info()
+                })
 
-def session_progress(data):
-    return  sessions("/Playing/Progress", "POST", json=data)
+    def get_date_modified(self, date, parent_id, media=None):
+        return  self.users("/Items", params={
+                    'ParentId': parent_id,
+                    'Recursive': False,
+                    'IsMissing': False,
+                    'IsVirtualUnaired': False,
+                    'IncludeItemTypes': media or None,
+                    'MinDateLastSaved': date,
+                    'Fields': info()
+                })
 
-def session_stop(data):
-    return  sessions("/Playing/Stopped", "POST", json=data)
+    def get_userdata_date_modified(self, date, parent_id, media=None):
+        return  self.users("/Items", params={
+                    'ParentId': parent_id,
+                    'Recursive': True,
+                    'IsMissing': False,
+                    'IsVirtualUnaired': False,
+                    'IncludeItemTypes': media or None,
+                    'MinDateLastSavedForUser': date,
+                    'Fields': info()
+                })
 
-def item_played(item_id, watched):
-    return  users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
+    def refresh_item(self, item_id):
+        return  self.items("/%s/Refresh" % item_id, "POST", json={
+                    'Recursive': True,
+                    'ImageRefreshMode': "FullRefresh",
+                    'MetadataRefreshMode': "FullRefresh",
+                    'ReplaceAllImages': False,
+                    'ReplaceAllMetadata': True
+                })
 
-def get_sync_queue(date, filters=None):
-    return  _get("Emby.Kodi.SyncQueue/{UserId}/GetItems", params={
-                'LastUpdateDT': date,
-                'filter': filters or None
-            })
+    def favorite(self, item_id, option=True):
+        return  self.users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE")
 
-def get_server_time():
-    return  _get("Emby.Kodi.SyncQueue/GetServerDateTime")
+    def get_system_info(self):
+        return  self._get("System/Configuration")
 
-def get_play_info(item_id, profile):
-    return  items("/%s/PlaybackInfo" % item_id, "POST", json={
-                'UserId': "{UserId}",
-                'DeviceProfile': profile,
-                'AutoOpenLiveStream': True
-            })
+    def post_capabilities(self, data):
+        return  self.sessions("/Capabilities/Full", "POST", json=data)
 
-def get_live_stream(item_id, play_id, token, profile):
-    return  _post("LiveStreams/Open", json={
-                'UserId': "{UserId}",
-                'DeviceProfile': profile,
-                'OpenToken': token,
-                'PlaySessionId': play_id,
-                'ItemId': item_id
-            })
+    def session_add_user(self, session_id, user_id, option=True):
+        return  self.sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE")
 
-def close_live_stream(live_id):
-    return  _post("LiveStreams/Close", json={
-                'LiveStreamId': live_id
-            })
+    def session_playing(self, data):
+        return  self.sessions("/Playing", "POST", json=data)
 
-def close_transcode(device_id):
-    return  _delete("Videos/ActiveEncodings", params={
-                'DeviceId': device_id
-            })
+    def session_progress(self, data):
+        return  self.sessions("/Playing/Progress", "POST", json=data)
 
-def delete_item(item_id):
-    return  items("/%s" % item_id, "DELETE")
+    def session_stop(self, data):
+        return  self.sessions("/Playing/Stopped", "POST", json=data)
+
+    def item_played(self, item_id, watched):
+        return  self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
+
+    def get_sync_queue(self, date, filters=None):
+        return  self._get("Emby.Kodi.SyncQueue/{UserId}/GetItems", params={
+                    'LastUpdateDT': date,
+                    'filter': filters or None
+                })
+
+    def get_server_time(self):
+        return  self._get("Emby.Kodi.SyncQueue/GetServerDateTime")
+
+    def get_play_info(self, item_id, profile):
+        return  self.items("/%s/PlaybackInfo" % item_id, "POST", json={
+                    'UserId': "{UserId}",
+                    'DeviceProfile': profile,
+                    'AutoOpenLiveStream': True
+                })
+
+    def get_live_stream(self, item_id, play_id, token, profile):
+        return  self._post("LiveStreams/Open", json={
+                    'UserId': "{UserId}",
+                    'DeviceProfile': profile,
+                    'OpenToken': token,
+                    'PlaySessionId': play_id,
+                    'ItemId': item_id
+                })
+
+    def close_live_stream(self, live_id):
+        return  self._post("LiveStreams/Close", json={
+                    'LiveStreamId': live_id
+                })
+
+    def close_transcode(self, device_id):
+        return  self._delete("Videos/ActiveEncodings", params={
+                    'DeviceId': device_id
+                })
+
+    def delete_item(self, item_id):
+        return  self.items("/%s" % item_id, "DELETE")