# -*- coding: utf-8 -*- import json import os import xbmcaddon import xbmcvfs import dialogs.serverconnect import dialogs.usersconnect import dialogs.loginconnect import dialogs.loginmanual import dialogs.servermanual import helper.loghandler import emby.main class Connect(): def __init__(self, Utils): self.Utils = Utils self.XML_PATH = (xbmcaddon.Addon("plugin.video.emby-next-gen").getAddonInfo('path'), "default", "1080i") self.LOG = helper.loghandler.LOG('EMBY.emby.connect.Connect') self.user = None self.config = None self.connect_manager = None self.EmbyServer = emby.main.Emby(self.Utils) def _save_servers(self, new_servers, default): credentials = self.get_credentials() if not new_servers: return credentials for new_server in new_servers: for server in credentials['Servers']: if server['Id'] == new_server['Id']: server.update(new_server) if default: credentials['Servers'].remove(server) credentials['Servers'].insert(0, server) break else: if default: credentials['Servers'].insert(0, new_server) else: credentials['Servers'].append(new_server) if default: default_server = new_servers[0] for server in credentials['Servers']: if server['Id'] == default_server['Id']: credentials['Servers'].remove(server) credentials['Servers'].insert(0, default_server) return credentials #Login into server. If server is None, then it will show the proper prompts to login, etc. #If a server id is specified then only a login dialog will be shown for that server. def register(self, options): self.LOG.info("--[ server/%s ]" % "DEFAULT") credentials = self.get_credentials() new_credentials = self.register_client(credentials, options, not self.Utils.Settings.SyncInstallRunDone) if new_credentials: server_id = new_credentials['Servers'][0]['Id'] credentials = self._save_servers(new_credentials['Servers'], server_id) new_credentials.update(credentials) self.save_credentials(new_credentials) return server_id, self.EmbyServer return False, None def save_credentials(self, credentials): path = self.Utils.translatePath("special://profile/addon_data/plugin.video.emby-next-gen/") if not xbmcvfs.exists(path): xbmcvfs.mkdirs(path) credentials = json.dumps(credentials, sort_keys=True, indent=4, ensure_ascii=False) with open(os.path.join(path, 'data.json'), 'wb') as outfile: outfile.write(credentials.encode('utf-8')) def get_credentials(self): path = self.Utils.translatePath("special://profile/addon_data/plugin.video.emby-next-gen/") if not xbmcvfs.exists(path): xbmcvfs.mkdirs(path) if xbmcvfs.exists(os.path.join(path, "data.json")): with open(os.path.join(path, 'data.json'), 'rb') as infile: credentials = json.load(infile) else: credentials = {} credentials['Servers'] = credentials.get('Servers', []) return credentials #Set Emby client def set_client(self): self.EmbyServer.Data['app.name'] = "Kodi" self.EmbyServer.Data['app.version'] = self.Utils.device_info['Version'] self.EmbyServer.Data['app.device_name'] = self.Utils.device_info['DeviceName'] self.EmbyServer.Data['app.device_id'] = self.Utils.device_info['DeviceId'] self.EmbyServer.Data['app.capabilities'] = None self.EmbyServer.Data['http.user_agent'] = "Emby-Kodi/%s" % self.Utils.device_info['Version'] self.EmbyServer.Data['auth.ssl'] = self.Utils.Settings.sslverify def register_client(self, credentials, options, server_selection): self.set_client() self.connect_manager = self.EmbyServer.auth state = self.EmbyServer.authenticate(credentials or {}, options or {}) if state: if state['State'] == 3: #SignedIn server_id = state['Servers'][0]['Id'] self.EmbyServer.server_id = server_id return state['Credentials'] if state['State'] == 0: #Unavailable return False if server_selection or state['State'] in (4, 1): #ConnectSignIn or ServerSelection result = self.select_servers(state) if not result: #Cancel return False elif state['State'] == 2: #ServerSignIn if 'ExchangeToken' not in state['Servers'][0]: result = self.login() if not result: return False elif state['State'] == 0: #Unavailable return False return self.register_client(state['Credentials'], options, False) return False #Save user info def get_user(self): self.user = self.EmbyServer.API.get_user(None) self.config = self.EmbyServer.API.get_system_info() self.Utils.Settings.set_settings('username', self.user['Name']) if 'PrimaryImageTag' in self.user: self.Utils.Settings.emby_UserImage = self.EmbyServer.API.get_user_artwork(self.user['Id']) def select_servers(self, state): if not state: state = self.connect_manager.connect({'enableAutoLogin': False}) if not state: return False user = state.get('ConnectUser') or {} Dialog = dialogs.serverconnect.ServerConnect("script-emby-connect-server.xml", *self.XML_PATH) Dialog.set_args(**{ 'connect_manager': self.connect_manager, 'username': user.get('DisplayName', ""), 'user_image': user.get('ImageUrl'), 'servers': state.get('Servers', []), 'emby_connect': not user }) Dialog.doModal() if Dialog.is_server_selected(): self.LOG.debug("Server selected: %s" % Dialog.get_server()) return True if Dialog.is_connect_login(): self.LOG.debug("Login with emby connect") self.login_connect(None) elif Dialog.is_manual_server(): self.LOG.debug("Adding manual server") self.manual_server(None) else: return False #"No server selected" return self.select_servers(None) #Return server or raise error def manual_server(self, manager): Dialog = dialogs.servermanual.ServerManual("script-emby-connect-server-manual.xml", *self.XML_PATH) Dialog.set_args(**{'connect_manager': manager or self.connect_manager}) Dialog.doModal() if Dialog.is_connected(): return Dialog.get_server() #raise RuntimeError("Server is not connected") return False #Return connect user or raise error def login_connect(self, manager): Dialog = dialogs.loginconnect.LoginConnect("script-emby-connect-login.xml", *self.XML_PATH) Dialog.set_args(**{'connect_manager': manager or self.connect_manager}) Dialog.doModal() if Dialog.is_logged_in(): return Dialog.get_user() return False #"Connect user is not logged in" def login(self): users = self.EmbyServer.API.get_public_users() server = self.EmbyServer.auth.get_serveraddress() if not users: return self.login_manual(None, None) Dialog = dialogs.usersconnect.UsersConnect("script-emby-connect-users.xml", *self.XML_PATH) Dialog.set_args(**{'server': server, 'users': users}) Dialog.doModal() if Dialog.is_user_selected(): user = Dialog.get_user() username = user['Name'] if user['HasPassword']: self.LOG.debug("User has password, present manual login") Result = self.login_manual(username, None) if Result: return Result else: return self.connect_manager.login(server, username, None, True, {}) elif Dialog.is_manual_login(): Result = self.login_manual(None, None) if Result: return Result else: return False #"No user selected" return self.login() #Return manual login user authenticated or raise error def login_manual(self, user, manager): Dialog = dialogs.loginmanual.LoginManual("script-emby-connect-login-manual.xml", *self.XML_PATH) Dialog.set_args(**{'connect_manager': manager or self.connect_manager, 'username': user or {}}) Dialog.doModal() if Dialog.is_logged_in(): return Dialog.get_user() return False #"User is not authenticated" #Stop client and remove server def remove_server(self, server_id): credentials = self.get_credentials() for server in credentials['Servers']: if server['Id'] == server_id: credentials['Servers'].remove(server) break self.save_credentials(credentials) self.LOG.info("[ remove server ] %s" % server_id) #Allow user to setup ssl verification for additional servers def set_ssl(self, server_id): value = self.Utils.Dialog("yesno", heading="{emby}", line1=self.Utils.Translate(33217)) credentials = self.get_credentials() for server in credentials['Servers']: if server['Id'] == server_id: server['verify'] = bool(value) self.save_credentials(credentials) self.LOG.info("[ ssl/%s/%s ]" % (server_id, server['verify'])) break