diff --git a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js index 462fca8162..d2f34ec330 100644 --- a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js +++ b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js @@ -1 +1,782 @@ -define(["events","apiclient","appStorage"],function(events,apiClientFactory,appStorage){"use strict";function getServerAddress(server,mode){switch(mode){case ConnectionMode.Local:return server.LocalAddress;case ConnectionMode.Manual:return server.ManualAddress;case ConnectionMode.Remote:return server.RemoteAddress;default:return server.ManualAddress||server.LocalAddress||server.RemoteAddress}}function paramsToString(params){var values=[];for(var key in params){var value=params[key];null!==value&&void 0!==value&&""!==value&&values.push(encodeURIComponent(key)+"="+encodeURIComponent(value))}return values.join("&")}function resolveFailure(instance,resolve){resolve({State:"Unavailable",ConnectUser:instance.connectUser()})}function mergeServers(credentialProvider,list1,list2){for(var i=0,length=list2.length;ibVal)return 1}return 0}var defaultTimeout=2e4,ConnectionMode={Local:0,Remote:1,Manual:2},ConnectionManager=function(credentialProvider,appName,appVersion,deviceName,deviceId,capabilities,devicePixelRatio){function onConnectUserSignIn(user){connectUser=user,events.trigger(self,"connectusersignedin",[user])}function onAuthenticated(apiClient,result,options,saveCredentials){var credentials=credentialProvider.credentials(),servers=credentials.Servers.filter(function(s){return s.Id===result.ServerId}),server=servers.length?servers[0]:apiClient.serverInfo();return!1!==options.updateDateLastAccessed&&(server.DateLastAccessed=(new Date).getTime()),server.Id=result.ServerId,saveCredentials?(server.UserId=result.User.Id,server.AccessToken=result.AccessToken):(server.UserId=null,server.AccessToken=null),credentialProvider.addOrUpdateServer(credentials.Servers,server),credentialProvider.credentials(credentials),apiClient.enableAutomaticBitrateDetection=options.enableAutomaticBitrateDetection,apiClient.serverInfo(server),afterConnected(apiClient,options),onLocalUserSignIn(server,apiClient.serverAddress(),result.User)}function afterConnected(apiClient,options){options=options||{},!1!==options.reportCapabilities&&apiClient.reportCapabilities(capabilities),apiClient.enableAutomaticBitrateDetection=options.enableAutomaticBitrateDetection,!1!==options.enableWebSocket&&(console.log("calling apiClient.ensureWebSocket"),apiClient.ensureWebSocket())}function onLocalUserSignIn(server,serverUrl,user){return self._getOrAddApiClient(server,serverUrl),(self.onLocalUserSignedIn?self.onLocalUserSignedIn.call(self,user):Promise.resolve()).then(function(){events.trigger(self,"localusersignedin",[user])})}function ensureConnectUser(credentials){return connectUser&&connectUser.Id===credentials.ConnectUserId?Promise.resolve():credentials.ConnectUserId&&credentials.ConnectAccessToken?(connectUser=null,getConnectUser(credentials.ConnectUserId,credentials.ConnectAccessToken).then(function(user){return onConnectUserSignIn(user),Promise.resolve()},function(){return Promise.resolve()})):Promise.resolve()}function getConnectUser(userId,accessToken){if(!userId)throw new Error("null userId");if(!accessToken)throw new Error("null accessToken");return ajax({type:"GET",url:"https://connect.emby.media/service/user?id="+userId,dataType:"json",headers:{"X-Application":appName+"/"+appVersion,"X-Connect-UserToken":accessToken}})}function addAuthenticationInfoFromConnect(server,serverUrl,credentials){if(!server.ExchangeToken)throw new Error("server.ExchangeToken cannot be null");if(!credentials.ConnectUserId)throw new Error("credentials.ConnectUserId cannot be null");var url=getEmbyServerUrl(serverUrl,"Connect/Exchange?format=json&ConnectUserId="+credentials.ConnectUserId),auth='MediaBrowser Client="'+appName+'", Device="'+deviceName+'", DeviceId="'+deviceId+'", Version="'+appVersion+'"';return ajax({type:"GET",url:url,dataType:"json",headers:{"X-MediaBrowser-Token":server.ExchangeToken,"X-Emby-Authorization":auth}}).then(function(auth){return server.UserId=auth.LocalUserId,server.AccessToken=auth.AccessToken,auth},function(){return server.UserId=null,server.AccessToken=null,Promise.reject()})}function validateAuthentication(server,serverUrl){return ajax({type:"GET",url:getEmbyServerUrl(serverUrl,"System/Info"),dataType:"json",headers:{"X-MediaBrowser-Token":server.AccessToken}}).then(function(systemInfo){return updateServerInfo(server,systemInfo),Promise.resolve()},function(){return server.UserId=null,server.AccessToken=null,Promise.resolve()})}function getImageUrl(localUser){if(connectUser&&connectUser.ImageUrl)return{url:connectUser.ImageUrl};if(localUser&&localUser.PrimaryImageTag){return{url:self.getApiClient(localUser).getUserImageUrl(localUser.Id,{tag:localUser.PrimaryImageTag,type:"Primary"}),supportsParams:!0}}return{url:null,supportsParams:!1}}function logoutOfServer(apiClient){var serverInfo=apiClient.serverInfo()||{},logoutInfo={serverId:serverInfo.Id};return apiClient.logout().then(function(){events.trigger(self,"localusersignedout",[logoutInfo])},function(){events.trigger(self,"localusersignedout",[logoutInfo])})}function getConnectServers(credentials){return console.log("Begin getConnectServers"),credentials.ConnectAccessToken&&credentials.ConnectUserId?ajax({type:"GET",url:"https://connect.emby.media/service/servers?userId="+credentials.ConnectUserId,dataType:"json",headers:{"X-Application":appName+"/"+appVersion,"X-Connect-UserToken":credentials.ConnectAccessToken}}).then(function(servers){return servers.map(function(i){return{ExchangeToken:i.AccessKey,ConnectServerId:i.Id,Id:i.SystemId,Name:i.Name,RemoteAddress:i.Url,LocalAddress:i.LocalAddress,UserLinkType:"guest"===(i.UserType||"").toLowerCase()?"Guest":"LinkedUser"}})},function(){return credentials.Servers.slice(0).filter(function(s){return s.ExchangeToken})}):Promise.resolve([])}function filterServers(servers,connectServers){return servers.filter(function(server){return!server.ExchangeToken||connectServers.filter(function(connectServer){return server.Id===connectServer.Id}).length>0})}function findServers(){return new Promise(function(resolve,reject){var onFinish=function(foundServers){var servers=foundServers.map(function(foundServer){var info={Id:foundServer.Id,LocalAddress:convertEndpointAddressToManualAddress(foundServer)||foundServer.Address,Name:foundServer.Name};return info.LastConnectionMode=info.ManualAddress?ConnectionMode.Manual:ConnectionMode.Local,info});resolve(servers)};require(["serverdiscovery"],function(serverDiscovery){serverDiscovery.findServers(1e3).then(onFinish,function(){onFinish([])})})})}function convertEndpointAddressToManualAddress(info){if(info.Address&&info.EndpointAddress){var address=info.EndpointAddress.split(":")[0],parts=info.Address.split(":");if(parts.length>1){var portString=parts[parts.length-1];isNaN(parseInt(portString))||(address+=":"+portString)}return normalizeAddress(address)}return null}function getTryConnectPromise(url,connectionMode,state,resolve,reject){console.log("getTryConnectPromise "+url),ajax({url:getEmbyServerUrl(url,"system/info/public"),timeout:defaultTimeout,type:"GET",dataType:"json"}).then(function(result){state.resolved||(state.resolved=!0,console.log("Reconnect succeeded to "+url),resolve({url:url,connectionMode:connectionMode,data:result}))},function(){state.resolved||(console.log("Reconnect failed to "+url),++state.rejects>=state.numAddresses&&reject())})}function tryReconnect(serverInfo){var addresses=[],addressesStrings=[];return!serverInfo.manualAddressOnly&&serverInfo.LocalAddress&&-1===addressesStrings.indexOf(serverInfo.LocalAddress)&&(addresses.push({url:serverInfo.LocalAddress,mode:ConnectionMode.Local,timeout:0}),addressesStrings.push(addresses[addresses.length-1].url)),serverInfo.ManualAddress&&-1===addressesStrings.indexOf(serverInfo.ManualAddress)&&(addresses.push({url:serverInfo.ManualAddress,mode:ConnectionMode.Manual,timeout:100}),addressesStrings.push(addresses[addresses.length-1].url)),!serverInfo.manualAddressOnly&&serverInfo.RemoteAddress&&-1===addressesStrings.indexOf(serverInfo.RemoteAddress)&&(addresses.push({url:serverInfo.RemoteAddress,mode:ConnectionMode.Remote,timeout:200}),addressesStrings.push(addresses[addresses.length-1].url)),console.log("tryReconnect: "+addressesStrings.join("|")),new Promise(function(resolve,reject){var state={};state.numAddresses=addresses.length,state.rejects=0,addresses.map(function(url){setTimeout(function(){state.resolved||getTryConnectPromise(url.url,url.mode,state,resolve,reject)},url.timeout)})})}function onSuccessfulConnection(server,systemInfo,connectionMode,serverUrl,options,resolve){var credentials=credentialProvider.credentials();options=options||{},credentials.ConnectAccessToken&&!1!==options.enableAutoLogin?ensureConnectUser(credentials).then(function(){server.ExchangeToken?addAuthenticationInfoFromConnect(server,serverUrl,credentials).then(function(){afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,!0,options,resolve)},function(){afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,!0,options,resolve)}):afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,!0,options,resolve)}):afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,!0,options,resolve)}function afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,verifyLocalAuthentication,options,resolve){if(options=options||{},!1===options.enableAutoLogin)server.UserId=null,server.AccessToken=null;else if(verifyLocalAuthentication&&server.AccessToken&&!1!==options.enableAutoLogin)return void validateAuthentication(server,serverUrl).then(function(){afterConnectValidated(server,credentials,systemInfo,connectionMode,serverUrl,!1,options,resolve)});updateServerInfo(server,systemInfo),server.LastConnectionMode=connectionMode,!1!==options.updateDateLastAccessed&&(server.DateLastAccessed=(new Date).getTime()),credentialProvider.addOrUpdateServer(credentials.Servers,server),credentialProvider.credentials(credentials);var result={Servers:[]};result.ApiClient=self._getOrAddApiClient(server,serverUrl),result.ApiClient.setSystemInfo(systemInfo),result.State=server.AccessToken&&!1!==options.enableAutoLogin?"SignedIn":"ServerSignIn",result.Servers.push(server),result.ApiClient.enableAutomaticBitrateDetection=options.enableAutomaticBitrateDetection,result.ApiClient.updateServerInfo(server,serverUrl);var resolveActions=function(){resolve(result),events.trigger(self,"connected",[result])};"SignedIn"===result.State?(afterConnected(result.ApiClient,options),result.ApiClient.getCurrentUser().then(function(user){onLocalUserSignIn(server,serverUrl,user).then(resolveActions,resolveActions)},resolveActions)):resolveActions()}function getCacheKey(feature,apiClient,options){options=options||{};var viewOnly=options.viewOnly,cacheKey="regInfo-"+apiClient.serverId();return viewOnly&&(cacheKey+="-viewonly"),cacheKey}function addAppInfoToConnectRequest(request){request.headers=request.headers||{},request.headers["X-Application"]=appName+"/"+appVersion}function exchangePin(pinInfo){if(!pinInfo)throw new Error("pinInfo cannot be null");var request={type:"POST",url:getConnectUrl("pin/authenticate"),data:{deviceId:pinInfo.DeviceId,pin:pinInfo.Pin},dataType:"json"};return addAppInfoToConnectRequest(request),ajax(request)}console.log("Begin ConnectionManager constructor");var self=this;this._apiClients=[];var connectUser;self.connectUser=function(){return connectUser},self._minServerVersion="3.2.33",self.appVersion=function(){return appVersion},self.appName=function(){return appName},self.capabilities=function(){return capabilities},self.deviceId=function(){return deviceId},self.credentialProvider=function(){return credentialProvider},self.connectUserId=function(){return credentialProvider.credentials().ConnectUserId},self.connectToken=function(){return credentialProvider.credentials().ConnectAccessToken},self.getServerInfo=function(id){return credentialProvider.credentials().Servers.filter(function(s){return s.Id===id})[0]},self.getLastUsedServer=function(){var servers=credentialProvider.credentials().Servers;return servers.sort(function(a,b){return(b.DateLastAccessed||0)-(a.DateLastAccessed||0)}),servers.length?servers[0]:null},self.addApiClient=function(apiClient){self._apiClients.push(apiClient);var existingServers=credentialProvider.credentials().Servers.filter(function(s){return stringEqualsIgnoreCase(s.ManualAddress,apiClient.serverAddress())||stringEqualsIgnoreCase(s.LocalAddress,apiClient.serverAddress())||stringEqualsIgnoreCase(s.RemoteAddress,apiClient.serverAddress())}),existingServer=existingServers.length?existingServers[0]:apiClient.serverInfo();if(existingServer.DateLastAccessed=(new Date).getTime(),existingServer.LastConnectionMode=ConnectionMode.Manual,existingServer.ManualAddress=apiClient.serverAddress(),apiClient.manualAddressOnly&&(existingServer.manualAddressOnly=!0),apiClient.serverInfo(existingServer),apiClient.onAuthenticated=function(instance,result){return onAuthenticated(instance,result,{},!0)},!existingServers.length){var credentials=credentialProvider.credentials();credentials.Servers=[existingServer],credentialProvider.credentials(credentials)}events.trigger(self,"apiclientcreated",[apiClient])},self.clearData=function(){console.log("connection manager clearing data"),connectUser=null;var credentials=credentialProvider.credentials();credentials.ConnectAccessToken=null,credentials.ConnectUserId=null,credentials.Servers=[],credentialProvider.credentials(credentials)},self._getOrAddApiClient=function(server,serverUrl){var apiClient=self.getApiClient(server.Id);return apiClient||(apiClient=new apiClientFactory(serverUrl,appName,appVersion,deviceName,deviceId,devicePixelRatio),self._apiClients.push(apiClient),apiClient.serverInfo(server),apiClient.onAuthenticated=function(instance,result){return onAuthenticated(instance,result,{},!0)},events.trigger(self,"apiclientcreated",[apiClient])),console.log("returning instance from getOrAddApiClient"),apiClient},self.getOrCreateApiClient=function(serverId){var credentials=credentialProvider.credentials(),servers=credentials.Servers.filter(function(s){return stringEqualsIgnoreCase(s.Id,serverId)});if(!servers.length)throw new Error("Server not found: "+serverId);var server=servers[0];return self._getOrAddApiClient(server,getServerAddress(server,server.LastConnectionMode))},self.user=function(apiClient){return new Promise(function(resolve,reject){function onLocalUserDone(e){var image=getImageUrl(localUser);resolve({localUser:localUser,name:connectUser?connectUser.Name:localUser?localUser.Name:null,imageUrl:image.url,supportsImageParams:image.supportsParams,connectUser:connectUser})}function onEnsureConnectUserDone(){apiClient&&apiClient.getCurrentUserId()?apiClient.getCurrentUser().then(function(u){localUser=u,onLocalUserDone()},onLocalUserDone):onLocalUserDone()}var localUser,credentials=credentialProvider.credentials();!credentials.ConnectUserId||!credentials.ConnectAccessToken||apiClient&&apiClient.getCurrentUserId()?onEnsureConnectUserDone():ensureConnectUser(credentials).then(onEnsureConnectUserDone,onEnsureConnectUserDone)})},self.logout=function(){console.log("begin connectionManager loguot");for(var promises=[],i=0,length=self._apiClients.length;i bVal) return 1 + } + return 0 + } + var defaultTimeout = 2e4, + ConnectionMode = { + Local: 0, + Remote: 1, + Manual: 2 + }, + ConnectionManager = function(credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { + function onConnectUserSignIn(user) { + connectUser = user, events.trigger(self, "connectusersignedin", [user]) + } + + function onAuthenticated(apiClient, result, options, saveCredentials) { + var credentials = credentialProvider.credentials(), + servers = credentials.Servers.filter(function(s) { + return s.Id === result.ServerId + }), + server = servers.length ? servers[0] : apiClient.serverInfo(); + return !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), server.Id = result.ServerId, saveCredentials ? (server.UserId = result.User.Id, server.AccessToken = result.AccessToken) : (server.UserId = null, server.AccessToken = null), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, apiClient.serverInfo(server), afterConnected(apiClient, options), onLocalUserSignIn(server, apiClient.serverAddress(), result.User) + } + + function afterConnected(apiClient, options) { + options = options || {}, !1 !== options.reportCapabilities && apiClient.reportCapabilities(capabilities), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, !1 !== options.enableWebSocket && (console.log("calling apiClient.ensureWebSocket"), apiClient.ensureWebSocket()) + } + + function onLocalUserSignIn(server, serverUrl, user) { + return self._getOrAddApiClient(server, serverUrl), (self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve()).then(function() { + events.trigger(self, "localusersignedin", [user]) + }) + } + + function ensureConnectUser(credentials) { + return connectUser && connectUser.Id === credentials.ConnectUserId ? Promise.resolve() : credentials.ConnectUserId && credentials.ConnectAccessToken ? (connectUser = null, getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function(user) { + return onConnectUserSignIn(user), Promise.resolve() + }, function() { + return Promise.resolve() + })) : Promise.resolve() + } + + function getConnectUser(userId, accessToken) { + if (!userId) throw new Error("null userId"); + if (!accessToken) throw new Error("null accessToken"); + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/user?id=" + userId, + dataType: "json", + headers: { + "X-Application": appName + "/" + appVersion, + "X-Connect-UserToken": accessToken + } + }) + } + + function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { + if (!server.ExchangeToken) throw new Error("server.ExchangeToken cannot be null"); + if (!credentials.ConnectUserId) throw new Error("credentials.ConnectUserId cannot be null"); + var url = getEmbyServerUrl(serverUrl, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId), + auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"'; + return ajax({ + type: "GET", + url: url, + dataType: "json", + headers: { + "X-MediaBrowser-Token": server.ExchangeToken, + "X-Emby-Authorization": auth + } + }).then(function(auth) { + return server.UserId = auth.LocalUserId, server.AccessToken = auth.AccessToken, auth + }, function() { + return server.UserId = null, server.AccessToken = null, Promise.reject() + }) + } + + function validateAuthentication(server, serverUrl) { + return ajax({ + type: "GET", + url: getEmbyServerUrl(serverUrl, "System/Info"), + dataType: "json", + headers: { + "X-MediaBrowser-Token": server.AccessToken + } + }).then(function(systemInfo) { + return updateServerInfo(server, systemInfo), Promise.resolve() + }, function() { + return server.UserId = null, server.AccessToken = null, Promise.resolve() + }) + } + + function getImageUrl(localUser) { + if (connectUser && connectUser.ImageUrl) return { + url: connectUser.ImageUrl + }; + if (localUser && localUser.PrimaryImageTag) { + return { + url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { + tag: localUser.PrimaryImageTag, + type: "Primary" + }), + supportsParams: !0 + } + } + return { + url: null, + supportsParams: !1 + } + } + + function logoutOfServer(apiClient) { + var serverInfo = apiClient.serverInfo() || {}, + logoutInfo = { + serverId: serverInfo.Id + }; + return apiClient.logout().then(function() { + events.trigger(self, "localusersignedout", [logoutInfo]) + }, function() { + events.trigger(self, "localusersignedout", [logoutInfo]) + }) + } + + function getConnectServers(credentials) { + return console.log("Begin getConnectServers"), credentials.ConnectAccessToken && credentials.ConnectUserId ? ajax({ + type: "GET", + url: "https://connect.emby.media/service/servers?userId=" + credentials.ConnectUserId, + dataType: "json", + headers: { + "X-Application": appName + "/" + appVersion, + "X-Connect-UserToken": credentials.ConnectAccessToken + } + }).then(function(servers) { + return servers.map(function(i) { + return { + ExchangeToken: i.AccessKey, + ConnectServerId: i.Id, + Id: i.SystemId, + Name: i.Name, + RemoteAddress: i.Url, + LocalAddress: i.LocalAddress, + UserLinkType: "guest" === (i.UserType || "").toLowerCase() ? "Guest" : "LinkedUser" + } + }) + }, function() { + return credentials.Servers.slice(0).filter(function(s) { + return s.ExchangeToken + }) + }) : Promise.resolve([]) + } + + function filterServers(servers, connectServers) { + return servers.filter(function(server) { + return !server.ExchangeToken || connectServers.filter(function(connectServer) { + return server.Id === connectServer.Id + }).length > 0 + }) + } + + function findServers() { + return new Promise(function(resolve, reject) { + var onFinish = function(foundServers) { + var servers = foundServers.map(function(foundServer) { + var info = { + Id: foundServer.Id, + LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address, + Name: foundServer.Name + }; + return info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local, info + }); + resolve(servers) + }; + require(["serverdiscovery"], function(serverDiscovery) { + serverDiscovery.findServers(1e3).then(onFinish, function() { + onFinish([]) + }) + }) + }) + } + + function convertEndpointAddressToManualAddress(info) { + if (info.Address && info.EndpointAddress) { + var address = info.EndpointAddress.split(":")[0], + parts = info.Address.split(":"); + if (parts.length > 1) { + var portString = parts[parts.length - 1]; + isNaN(parseInt(portString)) || (address += ":" + portString) + } + return normalizeAddress(address) + } + return null + } + + function getTryConnectPromise(url, connectionMode, state, resolve, reject) { + console.log("getTryConnectPromise " + url), ajax({ + url: getEmbyServerUrl(url, "system/info/public"), + timeout: defaultTimeout, + type: "GET", + dataType: "json" + }).then(function(result) { + state.resolved || (state.resolved = !0, console.log("Reconnect succeeded to " + url), resolve({ + url: url, + connectionMode: connectionMode, + data: result + })) + }, function() { + state.resolved || (console.log("Reconnect failed to " + url), ++state.rejects >= state.numAddresses && reject()) + }) + } + + function tryReconnect(serverInfo) { + var addresses = [], + addressesStrings = []; + return !serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress) && (addresses.push({ + url: serverInfo.LocalAddress, + mode: ConnectionMode.Local, + timeout: 0 + }), addressesStrings.push(addresses[addresses.length - 1].url)), serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress) && (addresses.push({ + url: serverInfo.ManualAddress, + mode: ConnectionMode.Manual, + timeout: 100 + }), addressesStrings.push(addresses[addresses.length - 1].url)), !serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress) && (addresses.push({ + url: serverInfo.RemoteAddress, + mode: ConnectionMode.Remote, + timeout: 200 + }), addressesStrings.push(addresses[addresses.length - 1].url)), console.log("tryReconnect: " + addressesStrings.join("|")), new Promise(function(resolve, reject) { + var state = {}; + state.numAddresses = addresses.length, state.rejects = 0, addresses.map(function(url) { + setTimeout(function() { + state.resolved || getTryConnectPromise(url.url, url.mode, state, resolve, reject) + }, url.timeout) + }) + }) + } + + function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) { + var credentials = credentialProvider.credentials(); + options = options || {}, credentials.ConnectAccessToken && !1 !== options.enableAutoLogin ? ensureConnectUser(credentials).then(function() { + server.ExchangeToken ? addAuthenticationInfoFromConnect(server, serverUrl, credentials).then(function() { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) + }, function() { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) + }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) + }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) + } + + function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { + if (options = options || {}, !1 === options.enableAutoLogin) server.UserId = null, server.AccessToken = null; + else if (verifyLocalAuthentication && server.AccessToken && !1 !== options.enableAutoLogin) return void validateAuthentication(server, serverUrl).then(function() { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !1, options, resolve) + }); + updateServerInfo(server, systemInfo), server.LastConnectionMode = connectionMode, !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials); + var result = { + Servers: [] + }; + result.ApiClient = self._getOrAddApiClient(server, serverUrl), result.ApiClient.setSystemInfo(systemInfo), result.State = server.AccessToken && !1 !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn", result.Servers.push(server), result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, result.ApiClient.updateServerInfo(server, serverUrl); + var resolveActions = function() { + resolve(result), events.trigger(self, "connected", [result]) + }; + "SignedIn" === result.State ? (afterConnected(result.ApiClient, options), result.ApiClient.getCurrentUser().then(function(user) { + onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions) + }, resolveActions)) : resolveActions() + } + + function getCacheKey(feature, apiClient, options) { + options = options || {}; + var viewOnly = options.viewOnly, + cacheKey = "regInfo-" + apiClient.serverId(); + return viewOnly && (cacheKey += "-viewonly"), cacheKey + } + + function addAppInfoToConnectRequest(request) { + request.headers = request.headers || {}, request.headers["X-Application"] = appName + "/" + appVersion + } + + function exchangePin(pinInfo) { + if (!pinInfo) throw new Error("pinInfo cannot be null"); + var request = { + type: "POST", + url: getConnectUrl("pin/authenticate"), + data: { + deviceId: pinInfo.DeviceId, + pin: pinInfo.Pin + }, + dataType: "json" + }; + return addAppInfoToConnectRequest(request), ajax(request) + } + console.log("Begin ConnectionManager constructor"); + var self = this; + this._apiClients = []; + var connectUser; + self.connectUser = function() { + return connectUser + }, self._minServerVersion = "3.2.33", self.appVersion = function() { + return appVersion + }, self.appName = function() { + return appName + }, self.capabilities = function() { + return capabilities + }, self.deviceId = function() { + return deviceId + }, self.credentialProvider = function() { + return credentialProvider + }, self.connectUserId = function() { + return credentialProvider.credentials().ConnectUserId + }, self.connectToken = function() { + return credentialProvider.credentials().ConnectAccessToken + }, self.getServerInfo = function(id) { + return credentialProvider.credentials().Servers.filter(function(s) { + return s.Id === id + })[0] + }, self.getLastUsedServer = function() { + var servers = credentialProvider.credentials().Servers; + return servers.sort(function(a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) + }), servers.length ? servers[0] : null + }, self.addApiClient = function(apiClient) { + self._apiClients.push(apiClient); + var existingServers = credentialProvider.credentials().Servers.filter(function(s) { + return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress()) + }), + existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); + if (existingServer.DateLastAccessed = (new Date).getTime(), existingServer.LastConnectionMode = ConnectionMode.Manual, existingServer.ManualAddress = apiClient.serverAddress(), apiClient.manualAddressOnly && (existingServer.manualAddressOnly = !0), apiClient.serverInfo(existingServer), apiClient.onAuthenticated = function(instance, result) { + return onAuthenticated(instance, result, {}, !0) + }, !existingServers.length) { + var credentials = credentialProvider.credentials(); + credentials.Servers = [existingServer], credentialProvider.credentials(credentials) + } + events.trigger(self, "apiclientcreated", [apiClient]) + }, self.clearData = function() { + console.log("connection manager clearing data"), connectUser = null; + var credentials = credentialProvider.credentials(); + credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentials.Servers = [], credentialProvider.credentials(credentials) + }, self._getOrAddApiClient = function(server, serverUrl) { + var apiClient = self.getApiClient(server.Id); + return apiClient || (apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio), self._apiClients.push(apiClient), apiClient.serverInfo(server), apiClient.onAuthenticated = function(instance, result) { + return onAuthenticated(instance, result, {}, !0) + }, events.trigger(self, "apiclientcreated", [apiClient])), console.log("returning instance from getOrAddApiClient"), apiClient + }, self.getOrCreateApiClient = function(serverId) { + var credentials = credentialProvider.credentials(), + servers = credentials.Servers.filter(function(s) { + return stringEqualsIgnoreCase(s.Id, serverId) + }); + if (!servers.length) throw new Error("Server not found: " + serverId); + var server = servers[0]; + return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) + }, self.user = function(apiClient) { + return new Promise(function(resolve, reject) { + function onLocalUserDone(e) { + var image = getImageUrl(localUser); + resolve({ + localUser: localUser, + name: connectUser ? connectUser.Name : localUser ? localUser.Name : null, + imageUrl: image.url, + supportsImageParams: image.supportsParams, + connectUser: connectUser + }) + } + + function onEnsureConnectUserDone() { + apiClient && apiClient.getCurrentUserId() ? apiClient.getCurrentUser().then(function(u) { + localUser = u, onLocalUserDone() + }, onLocalUserDone) : onLocalUserDone() + } + var localUser, credentials = credentialProvider.credentials(); + !credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId() ? onEnsureConnectUserDone() : ensureConnectUser(credentials).then(onEnsureConnectUserDone, onEnsureConnectUserDone) + }) + }, self.logout = function() { + console.log("begin connectionManager loguot"); + for (var promises = [], i = 0, length = self._apiClients.length; i < length; i++) { + var apiClient = self._apiClients[i]; + apiClient.accessToken() && promises.push(logoutOfServer(apiClient)) + } + return Promise.all(promises).then(function() { + for (var credentials = credentialProvider.credentials(), servers = credentials.Servers.filter(function(u) { + return "Guest" !== u.UserLinkType + }), j = 0, numServers = servers.length; j < numServers; j++) { + var server = servers[j]; + server.UserId = null, server.AccessToken = null, server.ExchangeToken = null + } + credentials.Servers = servers, credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentialProvider.credentials(credentials), connectUser && (connectUser = null, events.trigger(self, "connectusersignedout")) + }) + }, self.getSavedServers = function() { + var credentials = credentialProvider.credentials(), + servers = credentials.Servers.slice(0); + return servers.sort(function(a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) + }), servers + }, self.getAvailableServers = function() { + console.log("Begin getAvailableServers"); + var credentials = credentialProvider.credentials(); + return Promise.all([getConnectServers(credentials), findServers()]).then(function(responses) { + var connectServers = responses[0], + foundServers = responses[1], + servers = credentials.Servers.slice(0); + return mergeServers(credentialProvider, servers, foundServers), mergeServers(credentialProvider, servers, connectServers), servers = filterServers(servers, connectServers), servers.sort(function(a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) + }), credentials.Servers = servers, credentialProvider.credentials(credentials), servers + }) + }, self.connectToServers = function(servers, options) { + console.log("Begin connectToServers, with " + servers.length + " servers"); + var firstServer = servers.length ? servers[0] : null; + return firstServer ? self.connectToServer(firstServer, options).then(function(result) { + return "Unavailable" === result.State && (result.State = "ServerSelection"), console.log("resolving connectToServers with result.State: " + result.State), result + }) : Promise.resolve({ + Servers: servers, + State: servers.length || self.connectUser() ? "ServerSelection" : "ConnectSignIn", + ConnectUser: self.connectUser() + }) + }, self.connectToServer = function(server, options) { + return console.log("begin connectToServer"), new Promise(function(resolve, reject) { + options = options || {}, tryReconnect(server).then(function(result) { + var serverUrl = result.url, + connectionMode = result.connectionMode; + result = result.data, 1 === compareVersions(self.minServerVersion(), result.Version) ? (console.log("minServerVersion requirement not met. Server version: " + result.Version), resolve({ + State: "ServerUpdateNeeded", + Servers: [server] + })) : server.Id && result.Id !== server.Id ? (console.log("http request succeeded, but found a different server Id than what was expected"), resolveFailure(self, resolve)) : onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve) + }, function() { + resolveFailure(self, resolve) + }) + }) + }, self.connectToAddress = function(address, options) { + function onFail() { + return console.log("connectToAddress " + address + " failed"), Promise.resolve({ + State: "Unavailable", + ConnectUser: instance.connectUser() + }) + } + if (!address) return Promise.reject(); + address = normalizeAddress(address); + var instance = this, + server = { + ManualAddress: address, + LastConnectionMode: ConnectionMode.Manual + }; + return self.connectToServer(server, options).catch(onFail) + }, self.loginToConnect = function(username, password) { + return username && password ? ajax({ + type: "POST", + url: "https://connect.emby.media/service/user/authenticate", + data: { + nameOrEmail: username, + rawpw: password + }, + dataType: "json", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + headers: { + "X-Application": appName + "/" + appVersion + } + }).then(function(result) { + var credentials = credentialProvider.credentials(); + return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.User.Id, credentialProvider.credentials(credentials), onConnectUserSignIn(result.User), result + }) : Promise.reject() + }, self.signupForConnect = function(options) { + var email = options.email, + username = options.username, + password = options.password, + passwordConfirm = options.passwordConfirm; + if (!email) return Promise.reject({ + errorCode: "invalidinput" + }); + if (!username) return Promise.reject({ + errorCode: "invalidinput" + }); + if (!password) return Promise.reject({ + errorCode: "invalidinput" + }); + if (!passwordConfirm) return Promise.reject({ + errorCode: "passwordmatch" + }); + if (password !== passwordConfirm) return Promise.reject({ + errorCode: "passwordmatch" + }); + var data = { + email: email, + userName: username, + rawpw: password + }; + return options.grecaptcha && (data.grecaptcha = options.grecaptcha), ajax({ + type: "POST", + url: "https://connect.emby.media/service/register", + data: data, + dataType: "json", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + headers: { + "X-Application": appName + "/" + appVersion, + "X-CONNECT-TOKEN": "CONNECT-REGISTER" + } + }).catch(function(response) { + try { + return response.json() + } catch (err) { + throw err + } + }).then(function(result) { + if (result && result.Status) return "SUCCESS" === result.Status ? Promise.resolve(result) : Promise.reject({ + errorCode: result.Status + }); + Promise.reject() + }) + }, self.getUserInvitations = function() { + var connectToken = self.connectToken(); + if (!connectToken) throw new Error("null connectToken"); + if (!self.connectUserId()) throw new Error("null connectUserId"); + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/servers?userId=" + self.connectUserId() + "&status=Waiting", + dataType: "json", + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }) + }, self.deleteServer = function(serverId) { + if (!serverId) throw new Error("null serverId"); + var server = credentialProvider.credentials().Servers.filter(function(s) { + return s.Id === serverId + }); + return server = server.length ? server[0] : null, new Promise(function(resolve, reject) { + function onDone() { + var credentials = credentialProvider.credentials(); + credentials.Servers = credentials.Servers.filter(function(s) { + return s.Id !== serverId + }), credentialProvider.credentials(credentials), resolve() + } + if (!server.ConnectServerId) return void onDone(); + var connectToken = self.connectToken(), + connectUserId = self.connectUserId(); + if (!connectToken || !connectUserId) return void onDone(); + ajax({ + type: "DELETE", + url: "https://connect.emby.media/service/serverAuthorizations?serverId=" + server.ConnectServerId + "&userId=" + connectUserId, + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }).then(onDone, onDone) + }) + }, self.rejectServer = function(serverId) { + var connectToken = self.connectToken(); + if (!serverId) throw new Error("null serverId"); + if (!connectToken) throw new Error("null connectToken"); + if (!self.connectUserId()) throw new Error("null connectUserId"); + var url = "https://connect.emby.media/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); + return fetch(url, { + method: "DELETE", + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }) + }, self.acceptServer = function(serverId) { + var connectToken = self.connectToken(); + if (!serverId) throw new Error("null serverId"); + if (!connectToken) throw new Error("null connectToken"); + if (!self.connectUserId()) throw new Error("null connectUserId"); + return ajax({ + type: "GET", + url: "https://connect.emby.media/service/ServerAuthorizations/accept?serverId=" + serverId + "&userId=" + self.connectUserId(), + headers: { + "X-Connect-UserToken": connectToken, + "X-Application": appName + "/" + appVersion + } + }) + }, self.resetRegistrationInfo = function(apiClient) { + var cacheKey = getCacheKey("themes", apiClient, { + viewOnly: !0 + }); + appStorage.removeItem(cacheKey), cacheKey = getCacheKey("themes", apiClient, { + viewOnly: !1 + }), appStorage.removeItem(cacheKey) + }, self.getRegistrationInfo = function(feature, apiClient, options) { + var params = { + serverId: apiClient.serverId(), + deviceId: self.deviceId(), + deviceName: deviceName, + appName: appName, + appVersion: appVersion, + embyUserName: "" + }; + options = options || {}, options.viewOnly && (params.viewOnly = options.viewOnly); + var cacheKey = getCacheKey(feature, apiClient, options), + regInfo = JSON.parse(appStorage.getItem(cacheKey) || "{}"), + timeSinceLastValidation = (new Date).getTime() - (regInfo.lastValidDate || 0); + if (timeSinceLastValidation <= 864e5) return console.log("getRegistrationInfo returning cached info"), Promise.resolve(); + var updateDevicePromise; + regInfo.deviceId && regInfo.deviceId !== params.deviceId && (updateDevicePromise = ajax({ + url: "https://mb3admin.com/admin/service/registration/updateDevice?" + paramsToString({ + serverId: params.serverId, + oldDeviceId: regInfo.deviceId, + newDeviceId: params.deviceId + }), + type: "POST" + })), updateDevicePromise || (updateDevicePromise = Promise.resolve()); + var onFailure = function(err) { + if (console.log("getRegistrationInfo failed: " + err), timeSinceLastValidation <= 864e5 * (regInfo.cacheExpirationDays || 7)) return console.log("getRegistrationInfo returning cached info"), Promise.resolve(); + throw err + }; + return updateDevicePromise.then(function() { + return apiClient.getCurrentUser().then(function(user) { + return params.embyUserName = user.Name, "81f53802ea0247ad80618f55d9b4ec3c" === user.Id.toLowerCase() && "21585256623b4beeb26d5d3b09dec0ac" === params.serverId.toLowerCase() ? Promise.reject() : ajax({ + url: "https://mb3admin.com/admin/service/registration/validateDevice?" + paramsToString(params), + type: "POST", + dataType: "json" + }).then(function(response) { + return appStorage.setItem(cacheKey, JSON.stringify({ + lastValidDate: (new Date).getTime(), + deviceId: params.deviceId, + cacheExpirationDays: response.cacheExpirationDays + })), Promise.resolve() + }, function(response) { + var status = (response || {}).status; + return console.log("getRegistrationInfo response: " + status), 403 === status ? Promise.reject("overlimit") : status ? Promise.reject() : onFailure(response) + }) + }, onFailure) + }, onFailure) + }, self.createPin = function() { + var request = { + type: "POST", + url: getConnectUrl("pin"), + data: { + deviceId: deviceId + }, + dataType: "json" + }; + return addAppInfoToConnectRequest(request), ajax(request) + }, self.getPinStatus = function(pinInfo) { + if (!pinInfo) throw new Error("pinInfo cannot be null"); + var queryString = { + deviceId: pinInfo.DeviceId, + pin: pinInfo.Pin + }, + request = { + type: "GET", + url: getConnectUrl("pin") + "?" + paramsToString(queryString), + dataType: "json" + }; + return addAppInfoToConnectRequest(request), ajax(request) + }, self.exchangePin = function(pinInfo) { + if (!pinInfo) throw new Error("pinInfo cannot be null"); + return exchangePin(pinInfo).then(function(result) { + var credentials = credentialProvider.credentials(); + return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.UserId, credentialProvider.credentials(credentials), ensureConnectUser(credentials) + }) + } + }; + return ConnectionManager.prototype.connect = function(options) { + console.log("Begin connect"); + var instance = this; + return instance.getAvailableServers().then(function(servers) { + return instance.connectToServers(servers, options) + }) + }, ConnectionManager.prototype.isLoggedIntoConnect = function() { + return !(!this.connectToken() || !this.connectUserId()) + }, ConnectionManager.prototype.getApiClients = function() { + for (var servers = this.getSavedServers(), i = 0, length = servers.length; i < length; i++) { + var server = servers[i]; + server.Id && this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) + } + return this._apiClients + }, ConnectionManager.prototype.getApiClient = function(item) { + if (!item) throw new Error("item or serverId cannot be null"); + return item.ServerId && (item = item.ServerId), this._apiClients.filter(function(a) { + var serverInfo = a.serverInfo(); + return !serverInfo || serverInfo.Id === item + })[0] + }, ConnectionManager.prototype.minServerVersion = function(val) { + return val && (this._minServerVersion = val), this._minServerVersion + }, ConnectionManager.prototype.handleMessageReceived = function(msg) { + var serverId = msg.ServerId; + if (serverId) { + var apiClient = this.getApiClient(serverId); + if (apiClient) { + if ("string" == typeof msg.Data) try { + msg.Data = JSON.parse(msg.Data) + } catch (err) {} + apiClient.handleMessageReceived(msg) + } + } + }, ConnectionManager +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/addpluginpage.js b/dashboard-ui/scripts/addpluginpage.js index c167ab1a36..dbb921d714 100644 --- a/dashboard-ui/scripts/addpluginpage.js +++ b/dashboard-ui/scripts/addpluginpage.js @@ -1 +1,141 @@ -define(["jQuery","loading","libraryMenu","globalize","connectionManager","emby-linkbutton"],function($,loading,libraryMenu,globalize,connectionManager){"use strict";function populateHistory(packageInfo,page){for(var html="",i=0,length=Math.min(packageInfo.versions.length,10);i'+version.versionStr+" ("+version.classification+")",html+='
'+version.description+"
"}$("#revisionHistory",page).html(html)}function populateVersions(packageInfo,page,installedPlugin){for(var html="",i=0,length=packageInfo.versions.length;i'+version.versionStr+" ("+version.classification+")"}var selectmenu=$("#selectVersion",page).html(html);installedPlugin||$("#pCurrentVersion",page).hide().html("");var packageVersion=packageInfo.versions.filter(function(current){return"Release"==current.classification})[0];if(packageVersion||(packageVersion=packageInfo.versions.filter(function(current){return"Beta"==current.classification})[0]),packageVersion){var val=packageVersion.versionStr+"|"+packageVersion.classification;selectmenu.val(val)}}function renderPluginInfo(page,pkg,pluginSecurityInfo){if(!AppInfo.isNativeApp)if(pkg.isPremium){$(".premiumPackage",page).show();var regStatus="";if(pkg.isRegistered)regStatus+="

",regStatus+=globalize.translate("MessageFeatureIncludedWithSupporter");else{var expDateTime=new Date(pkg.expDate).getTime(),nowTime=(new Date).getTime();expDateTime<=nowTime?(regStatus+="

",regStatus+=globalize.translate("MessageTrialExpired")):expDateTime>new Date(1970,1,1).getTime()&&(regStatus+="

",regStatus+=globalize.translate("MessageTrialWillExpireIn").replace("{0}",Math.round(expDateTime-nowTime)/864e5))}if(regStatus+="

",$("#regStatus",page).html(regStatus),pluginSecurityInfo.IsMBSupporter)if($(".premiumDescription",page).hide(),$(".supporterDescription",page).hide(),pkg.price>0){$(".premiumHasPrice",page).show(),$("#featureId",page).val(pkg.featureId),$("#featureName",page).val(pkg.name),$("#amount",page).val(pkg.price),$("#regPrice",page).html("

"+globalize.translate("ValuePriceUSD").replace("{0}","$"+pkg.price.toFixed(2))+"

"),$("#ppButton",page).hide();var url="https://mb3admin.com/admin/service/user/getPayPalEmail?id="+pkg.owner;fetch(url).then(function(response){return response.json()}).then(function(dev){dev.payPalEmail&&($("#payPalEmail",page).val(dev.payPalEmail),$("#ppButton",page).show())})}else $(".premiumHasPrice",page).hide();else pkg.price?($(".premiumDescription",page).show(),$(".supporterDescription",page).hide()):($(".premiumDescription",page).hide(),$(".supporterDescription",page).show()),$("#ppButton",page).hide()}else $(".premiumPackage",page).hide()}function renderPackage(pkg,installedPlugins,pluginSecurityInfo,page){var installedPlugin=installedPlugins.filter(function(ip){return ip.Name==pkg.name})[0];if(populateVersions(pkg,page,installedPlugin),populateHistory(pkg,page),$(".pluginName",page).html(pkg.name),"Server"==pkg.targetSystem)$("#btnInstallDiv",page).removeClass("hide"),$("#nonServerMsg",page).hide(),$("#pSelectVersion",page).removeClass("hide");else{$("#btnInstallDiv",page).addClass("hide"),$("#pSelectVersion",page).addClass("hide");var msg=globalize.translate("MessageInstallPluginFromApp");$("#nonServerMsg",page).html(msg).show()}if(pkg.shortDescription?$("#tagline",page).show().html(pkg.shortDescription):$("#tagline",page).hide(),$("#overview",page).html(pkg.overview||""),$("#developer",page).html(pkg.owner),renderPluginInfo(page,pkg,pluginSecurityInfo),pkg.richDescUrl?($("#pViewWebsite",page).show(),$("#pViewWebsite a",page).attr("href",pkg.richDescUrl)):$("#pViewWebsite",page).hide(),pkg.previewImage||pkg.thumbImage){var img=pkg.previewImage?pkg.previewImage:pkg.thumbImage;$("#pPreviewImage",page).show().html("")}else $("#pPreviewImage",page).hide().html("");if(installedPlugin){var currentVersionText=globalize.translate("MessageYouHaveVersionInstalled").replace("{0}",""+installedPlugin.Version+"");$("#pCurrentVersion",page).show().html(currentVersionText)}else $("#pCurrentVersion",page).hide().html("");loading.hide()}function alertText(options){require(["alert"],function(alert){alert(options)})}function performInstallation(page,packageName,guid,updateClass,version){var developer=$("#developer",page).html().toLowerCase(),alertCallback=function(confirmed){confirmed&&(loading.show(),page.querySelector("#btnInstall").disabled=!0,ApiClient.installPlugin(packageName,guid,updateClass,version).then(function(){loading.hide(),alertText(globalize.translate("PluginInstalledMessage"))}))};if("luke"!=developer&&"ebr"!=developer){loading.hide();var msg=globalize.translate("MessagePluginInstallDisclaimer");msg+="
",msg+="
",msg+=globalize.translate("PleaseConfirmPluginInstallation"),require(["confirm"],function(confirm){confirm(msg,globalize.translate("HeaderConfirmPluginInstallation")).then(function(){alertCallback(!0)},function(){alertCallback(!1)})})}else alertCallback(!0)}return function(view,params){var onSubmit=function(){loading.show();var page=$(this).parents("#addPluginPage")[0],name=params.name,guid=params.guid;return ApiClient.getInstalledPlugins().then(function(plugins){var installedPlugin=plugins.filter(function(ip){return ip.Name==name})[0],vals=$("#selectVersion",page).val().split("|"),version=vals[0];installedPlugin&&installedPlugin.Version==version?(loading.hide(),Dashboard.alert({message:globalize.translate("MessageAlreadyInstalled"),title:globalize.translate("HeaderPluginInstallation")})):performInstallation(page,name,guid,vals[1],version)}),!1};$(".addPluginForm",view).on("submit",onSubmit),view.addEventListener("viewshow",function(){var page=this;loading.show();var name=params.name,guid=params.guid,promise1=ApiClient.getPackageInfo(name,guid),promise2=ApiClient.getInstalledPlugins();connectionManager.getRegistrationInfo("themes",ApiClient,{viewOnly:!0}),Promise.all([promise1,promise2]).then(function(responses){connectionManager.getRegistrationInfo("themes",ApiClient,{viewOnly:!0}).then(function(){renderPackage(responses[0],responses[1],{IsMBSupporter:!0},page)},function(){renderPackage(responses[0],responses[1],{},page)})})})}}); \ No newline at end of file +define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-linkbutton"], function($, loading, libraryMenu, globalize, connectionManager) { + "use strict"; + + function populateHistory(packageInfo, page) { + for (var html = "", i = 0, length = Math.min(packageInfo.versions.length, 10); i < length; i++) { + var version = packageInfo.versions[i]; + html += '

' + version.versionStr + " (" + version.classification + ")

", html += '
' + version.description + "
" + } + $("#revisionHistory", page).html(html) + } + + function populateVersions(packageInfo, page, installedPlugin) { + for (var html = "", i = 0, length = packageInfo.versions.length; i < length; i++) { + var version = packageInfo.versions[i]; + html += '" + } + var selectmenu = $("#selectVersion", page).html(html); + installedPlugin || $("#pCurrentVersion", page).hide().html(""); + var packageVersion = packageInfo.versions.filter(function(current) { + return "Release" == current.classification + })[0]; + if (packageVersion || (packageVersion = packageInfo.versions.filter(function(current) { + return "Beta" == current.classification + })[0]), packageVersion) { + var val = packageVersion.versionStr + "|" + packageVersion.classification; + selectmenu.val(val) + } + } + + function renderPluginInfo(page, pkg, pluginSecurityInfo) { + if (!AppInfo.isNativeApp) + if (pkg.isPremium) { + $(".premiumPackage", page).show(); + var regStatus = ""; + if (pkg.isRegistered) regStatus += "

", regStatus += globalize.translate("MessageFeatureIncludedWithSupporter"); + else { + var expDateTime = new Date(pkg.expDate).getTime(), + nowTime = (new Date).getTime(); + expDateTime <= nowTime ? (regStatus += "

", regStatus += globalize.translate("MessageTrialExpired")) : expDateTime > new Date(1970, 1, 1).getTime() && (regStatus += "

", regStatus += globalize.translate("MessageTrialWillExpireIn").replace("{0}", Math.round(expDateTime - nowTime) / 864e5)) + } + if (regStatus += "

", $("#regStatus", page).html(regStatus), pluginSecurityInfo.IsMBSupporter) + if ($(".premiumDescription", page).hide(), $(".supporterDescription", page).hide(), pkg.price > 0) { + $(".premiumHasPrice", page).show(), $("#featureId", page).val(pkg.featureId), $("#featureName", page).val(pkg.name), $("#amount", page).val(pkg.price), $("#regPrice", page).html("

" + globalize.translate("ValuePriceUSD").replace("{0}", "$" + pkg.price.toFixed(2)) + "

"), $("#ppButton", page).hide(); + var url = "https://mb3admin.com/admin/service/user/getPayPalEmail?id=" + pkg.owner; + fetch(url).then(function(response) { + return response.json() + }).then(function(dev) { + dev.payPalEmail && ($("#payPalEmail", page).val(dev.payPalEmail), $("#ppButton", page).show()) + }) + } else $(".premiumHasPrice", page).hide(); + else pkg.price ? ($(".premiumDescription", page).show(), $(".supporterDescription", page).hide()) : ($(".premiumDescription", page).hide(), $(".supporterDescription", page).show()), $("#ppButton", page).hide() + } else $(".premiumPackage", page).hide() + } + + function renderPackage(pkg, installedPlugins, pluginSecurityInfo, page) { + var installedPlugin = installedPlugins.filter(function(ip) { + return ip.Name == pkg.name + })[0]; + if (populateVersions(pkg, page, installedPlugin), populateHistory(pkg, page), $(".pluginName", page).html(pkg.name), "Server" == pkg.targetSystem) $("#btnInstallDiv", page).removeClass("hide"), $("#nonServerMsg", page).hide(), $("#pSelectVersion", page).removeClass("hide"); + else { + $("#btnInstallDiv", page).addClass("hide"), $("#pSelectVersion", page).addClass("hide"); + var msg = globalize.translate("MessageInstallPluginFromApp"); + $("#nonServerMsg", page).html(msg).show() + } + if (pkg.shortDescription ? $("#tagline", page).show().html(pkg.shortDescription) : $("#tagline", page).hide(), $("#overview", page).html(pkg.overview || ""), $("#developer", page).html(pkg.owner), renderPluginInfo(page, pkg, pluginSecurityInfo), pkg.richDescUrl ? ($("#pViewWebsite", page).show(), $("#pViewWebsite a", page).attr("href", pkg.richDescUrl)) : $("#pViewWebsite", page).hide(), pkg.previewImage || pkg.thumbImage) { + var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage; + $("#pPreviewImage", page).show().html("") + } else $("#pPreviewImage", page).hide().html(""); + if (installedPlugin) { + var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled").replace("{0}", "" + installedPlugin.Version + ""); + $("#pCurrentVersion", page).show().html(currentVersionText) + } else $("#pCurrentVersion", page).hide().html(""); + loading.hide() + } + + function alertText(options) { + require(["alert"], function(alert) { + alert(options) + }) + } + + function performInstallation(page, packageName, guid, updateClass, version) { + var developer = $("#developer", page).html().toLowerCase(), + alertCallback = function(confirmed) { + confirmed && (loading.show(), page.querySelector("#btnInstall").disabled = !0, ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() { + loading.hide(), alertText(globalize.translate("PluginInstalledMessage")) + })) + }; + if ("luke" != developer && "ebr" != developer) { + loading.hide(); + var msg = globalize.translate("MessagePluginInstallDisclaimer"); + msg += "
", msg += "
", msg += globalize.translate("PleaseConfirmPluginInstallation"), require(["confirm"], function(confirm) { + confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function() { + alertCallback(!0) + }, function() { + alertCallback(!1) + }) + }) + } else alertCallback(!0) + } + return function(view, params) { + var onSubmit = function() { + loading.show(); + var page = $(this).parents("#addPluginPage")[0], + name = params.name, + guid = params.guid; + return ApiClient.getInstalledPlugins().then(function(plugins) { + var installedPlugin = plugins.filter(function(ip) { + return ip.Name == name + })[0], + vals = $("#selectVersion", page).val().split("|"), + version = vals[0]; + installedPlugin && installedPlugin.Version == version ? (loading.hide(), Dashboard.alert({ + message: globalize.translate("MessageAlreadyInstalled"), + title: globalize.translate("HeaderPluginInstallation") + })) : performInstallation(page, name, guid, vals[1], version) + }), !1 + }; + $(".addPluginForm", view).on("submit", onSubmit), view.addEventListener("viewshow", function() { + var page = this; + loading.show(); + var name = params.name, + guid = params.guid, + promise1 = ApiClient.getPackageInfo(name, guid), + promise2 = ApiClient.getInstalledPlugins(); + connectionManager.getRegistrationInfo("themes", ApiClient, { + viewOnly: !0 + }), Promise.all([promise1, promise2]).then(function(responses) { + connectionManager.getRegistrationInfo("themes", ApiClient, { + viewOnly: !0 + }).then(function() { + renderPackage(responses[0], responses[1], { + IsMBSupporter: !0 + }, page) + }, function() { + renderPackage(responses[0], responses[1], {}, page) + }) + }) + }) + } +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/supporterkeypage.js b/dashboard-ui/scripts/supporterkeypage.js index fddc5e3e38..415934da74 100644 --- a/dashboard-ui/scripts/supporterkeypage.js +++ b/dashboard-ui/scripts/supporterkeypage.js @@ -1 +1,141 @@ -define(["fetchHelper","dom","registrationServices","loading","confirm","globalize","connectionManager","emby-linkbutton","emby-collapse","emby-input","emby-button"],function(fetchHelper,dom,registrationServices,loading,confirm,globalize,connectionManager){"use strict";function getPluginSecurityInfo(){var apiClient=ApiClient;return apiClient.getJSON(apiClient.getUrl("Plugins/SecurityInfo"))}function load(page){loading.show(),getPluginSecurityInfo().then(function(info){page.querySelector("#txtSupporterKey").value=info.SupporterKey||"",info.SupporterKey&&!info.IsMBSupporter?(page.querySelector("#txtSupporterKey").classList.add("invalidEntry"),page.querySelector(".notSupporter").classList.remove("hide")):(page.querySelector("#txtSupporterKey").classList.remove("invalidEntry"),page.querySelector(".notSupporter").classList.add("hide")),info.IsMBSupporter?(page.querySelector(".supporterContainer").classList.add("hide"),getPremiereStatus(info.SupporterKey).then(function(statusInfo){if(statusInfo){var statusLine,indicator=page.querySelector("#status-indicator .listItemIcon"),extendedPlans=page.querySelector("#extended-plans");switch(extendedPlans.innerHTML=globalize.translate("MessagePremiereExtendedPlans",'',""),statusInfo.deviceStatus){case 2:statusLine=globalize.translate("MessagePremiereStatusOver",statusInfo.planType),indicator.classList.add("expiredBackground"),indicator.classList.remove("nearExpiredBackground"),indicator.innerHTML="",extendedPlans.classList.remove("hide");break;case 1:statusLine=globalize.translate("MessagePremiereStatusClose",statusInfo.planType),indicator.classList.remove("expiredBackground"),indicator.classList.add("nearExpiredBackground"),indicator.innerHTML="",extendedPlans.classList.remove("hide");break;default:statusLine=globalize.translate("MessagePremiereStatusGood",statusInfo.planType),indicator.classList.remove("expiredBackground"),indicator.classList.remove("nearExpiredBackground"),indicator.innerHTML="",extendedPlans.classList.add("hide")}page.querySelector("#premiere-status").innerHTML=statusLine;var subsElement=page.querySelector("#premiere-subs");if(statusInfo.subscriptions&&statusInfo.subscriptions.length>0){page.querySelector("#premiere-subs-content").innerHTML=getSubscriptionHtml(statusInfo.subscriptions,info.SupporterKey);var sub=page.querySelector(".lnkSubscription");sub&&sub.addEventListener("click",cancelSub),subsElement.classList.remove("hide")}else subsElement.classList.add("hide");page.querySelector(".isSupporter").classList.remove("hide")}})):(page.querySelector(".supporterContainer").classList.remove("hide"),page.querySelector(".isSupporter").classList.add("hide")),loading.hide()})}function getPremiereStatus(key){var postData="key="+key+"&serverId="+ApiClient.serverId();return fetchHelper.ajax({url:"https://mb3admin.com/admin/service/registration/getStatus",type:"POST",data:postData,contentType:"application/x-www-form-urlencoded",dataType:"json"})}function getSubscriptionHtml(subs,key){return subs.map(function(item){var itemHtml="",makeLink=item.autoRenew&&"Stripe"==item.store,tagName=makeLink?"button":"div";return itemHtml+=(tagName='