import events from "./events.js"; import { wakeOnLan, appStorage, appHost } from "./../common/servicelocator.js"; import queryString from "./../common/querystring.js"; let localPrefix = "local"; function isLocalId(str) { return str && str.startsWith(localPrefix); } function isNotLocalId(id) { return !isLocalId(id); } function isLocalItem(item) { if (item) { item = item.Id; if ("string" == typeof item && isLocalId(item)) return !0; } return !1; } function replaceAll(originalString, strReplace, strWith) { strReplace = new RegExp(strReplace, "ig"); return originalString.replace(strReplace, strWith); } function getAbortError() { var err = new Error("AbortError"); return (err.name = "AbortError"), err; } function getFetchPromise(instance, request, signal) { if (signal && signal.aborted) return Promise.reject(getAbortError()); var abortController, boundAbort, headers = request.headers || {}, fetchRequest = ("json" === request.dataType && (headers.accept = "application/json"), { headers: headers, method: request.type, credentials: "same-origin" }); request.timeout && ((boundAbort = (abortController = new AbortController()).abort.bind( abortController )), signal && signal.addEventListener("abort", boundAbort), setTimeout(boundAbort, request.timeout), (signal = abortController.signal)), signal && (fetchRequest.signal = signal); let contentType = request.contentType, url = (request.data && ("string" == typeof request.data ? (fetchRequest.body = request.data) : ((fetchRequest.body = queryString.paramsToString(request.data)), (contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8"))), request.url); return ( "application/json" === contentType && ((contentType = "text/plain"), (url = url + (url.includes("?") ? "&" : "?") + "reqformat=json")), contentType && (headers["Content-Type"] = contentType), fetch(url, fetchRequest) ); } function setSavedEndpointInfo(instance, info) { instance._endPointInfo = info; } function setServerAddress(instance, address) { (instance._serverAddress = address), events.trigger(instance, "serveraddresschanged", [ { apiClient: instance, address: address }, ]); } function onNetworkChanged(instance, resetAddress) { resetAddress && ((instance.connected = !1), (resetAddress = getAddresses(instance.serverInfo())).length) && setServerAddress(instance, resetAddress[0].url), setSavedEndpointInfo(instance, null); } function isLocalHostAddress(address) { return ( !!address.includes("://127.0.0.1") || !!address.toLowerCase().includes("://localhost") ); } function getAddresses(serverInfo) { var addresses = [], addressesStrings = []; return ( serverInfo.ManualAddress && isLocalHostAddress(serverInfo.ManualAddress) && !addressesStrings.includes(serverInfo.ManualAddress.toLowerCase()) && (addresses.push({ url: serverInfo.ManualAddress }), addressesStrings.push(addresses[addresses.length - 1].url.toLowerCase())), serverInfo.LocalAddress && !addressesStrings.includes(serverInfo.LocalAddress.toLowerCase()) && (addresses.push({ url: serverInfo.LocalAddress }), addressesStrings.push(addresses[addresses.length - 1].url.toLowerCase())), serverInfo.ManualAddress && !addressesStrings.includes(serverInfo.ManualAddress.toLowerCase()) && (addresses.push({ url: serverInfo.ManualAddress }), addressesStrings.push(addresses[addresses.length - 1].url.toLowerCase())), serverInfo.RemoteAddress && !addressesStrings.includes(serverInfo.RemoteAddress.toLowerCase()) && (addresses.push({ url: serverInfo.RemoteAddress }), addressesStrings.push(addresses[addresses.length - 1].url.toLowerCase())), console.log("getAddresses: " + addressesStrings.join("|")), addresses ); } function tryReconnectToUrl(instance, url, delay, signal) { return ( console.log("tryReconnectToUrl: " + url), setTimeoutPromise(delay).then(() => getFetchPromise( instance, { url: instance.getUrl("system/info/public", null, url), type: "GET", dataType: "json", timeout: 15e3, }, signal ).then(() => url) ) ); } function setTimeoutPromise(timeout) { return new Promise((resolve) => { setTimeout(resolve, timeout); }); } function tryReconnectInternal(instance, signal) { var addresses = getAddresses(instance.serverInfo()); if (!addresses.length) return Promise.reject(); if (1 === addresses.length) return Promise.resolve(addresses[0].url); let abortController = new AbortController(); var boundAbort = abortController.abort.bind(abortController), promises = (signal && signal.addEventListener("abort", boundAbort), (signal = abortController.signal), []); for (let i = 0, length = addresses.length; i < length; i++) promises.push( tryReconnectToUrl(instance, addresses[i].url, 200 * i, signal) ); return Promise.any(promises).then( (url) => ( instance.serverAddress(url), abortController.abort(), Promise.resolve(url) ) ); } function tryReconnect(instance, signal, retryCount = 0) { var promise = tryReconnectInternal(instance, signal); return 2 <= retryCount ? promise : promise.catch( (err) => ( console.log("error in tryReconnectInternal: " + (err || "")), setTimeoutPromise(500).then(() => tryReconnect(instance, signal, retryCount + 1) ) ) ); } function getUserCacheKey(userId, serverId) { return `user-${userId}-` + serverId; } function getCachedUser(instance, userId) { instance = instance.serverId(); return instance && (userId = appStorage.getItem(getUserCacheKey(userId, instance))) ? ((userId = JSON.parse(userId)) && setUserProperties(userId, instance), userId) : null; } function isUserLoggedIn(instance, userId) { var allUsers = instance._allUsers || []; for (let i = 0, length = allUsers.length; i < length; i++) if (allUsers[i].UserId === userId) return !0; return userId === instance.getCurrentUserId(); } function saveUserInCache(instance, user, forceSave) { setUserProperties(user, instance.serverId()), (forceSave || isUserLoggedIn(instance, user.Id)) && ((user.DateLastFetched = Date.now()), appStorage.setItem( getUserCacheKey(user.Id, user.ServerId), JSON.stringify(user) )); } function removeCachedUser(userId, serverId) { appStorage.removeItem(getUserCacheKey(userId, serverId)); } function updateCachedUser(instance, userId) { return instance.getUser(userId, !1); } function updateCachedUserConfig(instance, userId, config) { var user = getCachedUser(instance, userId); return user ? ((user.Configuration = Object.assign(user.Configuration, config || {})), saveUserInCache(instance, user), Promise.resolve()) : updateCachedUser(instance, userId); } function onWebSocketMessage(msg) { onMessageReceivedInternal(this, (msg = JSON.parse(msg.data))); } let messageIdsReceived = {}; function onMessageReceivedInternal(instance, msg) { var messageId = msg.MessageId; if (messageId) { if (messageIdsReceived[messageId]) return; messageIdsReceived[messageId] = !0; } var user, messageId = msg.MessageType; "UserUpdated" === messageId || "UserConfigurationUpdated" === messageId || "UserPolicyUpdated" === messageId ? (user = msg.Data).Id === instance.getCurrentUserId() && (saveUserInCache(instance, user), (instance._userViewsPromise = null)) : "LibraryChanged" === messageId && (instance._userViewsPromise = null), events.trigger(instance, "message", [msg]); } function onWebSocketOpen() { console.log("web socket connection opened"), events.trigger(this, "websocketopen"); let list = this.messageListeners; if (list) for (let i = 0, length = (list = list.slice(0)).length; i < length; i++) { var listener = list[i]; this.startMessageListener(listener.name, listener.options); } } function onWebSocketError() { events.trigger(this, "websocketerror"); } function setSocketOnClose(apiClient, socket) { socket.onclose = () => { console.log("web socket closed"), apiClient._webSocket === socket && (console.log("nulling out web socket"), (apiClient._webSocket = null)), setTimeout(() => { events.trigger(apiClient, "websocketclose"); }, 0); }; } function getNavigatorMaxBandwidth() { if ("undefined" != typeof navigator) { var connection = navigator.connection; if (connection) { let downlink = connection.downlink; if (downlink && 0 < downlink && downlink < Number.POSITIVE_INFINITY) return ( (downlink = downlink * 1e6 * 0.7), (downlink = parseInt(downlink)) ); if ( (downlink = connection.downlinkMax) && 0 < downlink && downlink < Number.POSITIVE_INFINITY ) return ( (downlink = downlink * 1e6 * 0.7), (downlink = parseInt(downlink)) ); } } return null; } function detectBitrateWithEndpointInfo(instance, { IsInNetwork }) { return IsInNetwork ? 2e8 : getNavigatorMaxBandwidth() || 4000002; } function getRemoteImagePrefix(instance, options) { var urlPrefix = "Items/" + options.itemId; return delete options.itemId, urlPrefix; } function modifyEpgRow(result) { (result.Type = "EpgChannel"), (result.ServerId = this.serverId()), (result.Id = result.Channel.Id); } function modifyEpgResponse(result) { return result.Items.forEach(modifyEpgRow.bind(this)), result; } function mapVirtualFolder(item) { (item.Type = "VirtualFolder"), (item.Id = item.ItemId), (item.IsFolder = !0); } function setSyncJobProperties(item, apiClient) { (item.Type = "SyncJob"), (item.ServerId = apiClient.serverId()); } function setUsersProperties(items, serverId) { for (let i = 0, length = items.length; i < length; i++) setUserProperties(items[i], serverId); return Promise.resolve(items); } function setUserProperties(user, serverId) { (user.Type = "User"), (user.ServerId = serverId); } function setLogsProperties(instance, items) { var serverId = instance.serverId(), canDownload = appHost.supports("filedownload"); for (let i = 0, length = items.length; i < length; i++) { var log = items[i]; (log.ServerId = serverId), (log.Type = "Log"), (log.Id = log.Name), (log.CanDownload = canDownload), (log.CanShare = !1); } return items; } function setApiKeysProperties(instance, response) { var serverId = instance.serverId(); for (let i = 0, length = response.Items.length; i < length; i++) { var log = response.Items[i]; (log.ServerId = serverId), (log.Type = "ApiKey"), (log.CanDelete = !0); } return response; } function normalizeImageOptions({ _devicePixelRatio }, options) { !1 !== options.adjustForPixelRatio && (_devicePixelRatio = _devicePixelRatio || 1) && (options.width && (options.width = Math.round(options.width * _devicePixelRatio)), options.height && (options.height = Math.round(options.height * _devicePixelRatio)), options.maxWidth && (options.maxWidth = Math.round(options.maxWidth * _devicePixelRatio)), options.maxHeight) && (options.maxHeight = Math.round(options.maxHeight * _devicePixelRatio)), delete options.adjustForPixelRatio, !1 === options.keepAnimation && delete options.keepAnimation, options.quality || ("Backdrop" === options.type ? (options.quality = 70) : (options.quality = 90)); } function fillTagProperties(result) { var serverId = this.serverId(), items = result.Items || result; for (let i = 0, length = items.length; i < length; i++) { var item = items[i]; (item.ServerId = serverId), (item.Type = "Tag"); } return result; } function mapToId(i) { return i.Id; } function mapToAccessToken(i) { return i.AccessToken; } function removeItemAll(arr, value) { let i = 0; for (; i < arr.length; ) arr[i] === value ? arr.splice(i, 1) : ++i; return arr; } let startingPlaySession = Date.now(); function onUserDataUpdated(userData) { var instance = this.instance, itemId = this.itemId, userId = this.userId; return ( (userData.ItemId = itemId), events.trigger(instance, "message", [ { MessageType: "UserDataChanged", Data: { UserId: userId, UserDataList: [userData], IsLocalEvent: !0 }, }, ]), userData ); } function onSeriesTimerCreated(result) { var instance = this.instance; return ( (result = result || {}), events.trigger(instance, "message", [ { MessageType: "SeriesTimerCreated", Data: Object.assign({ IsLocalEvent: !0 }, result), }, ]), result ); } function onSeriesTimerUpdated(result) { var instance = this.instance, itemId = this.itemId; return ( events.trigger(instance, "message", [ { MessageType: "SeriesTimerUpdated", Data: { Id: itemId, IsLocalEvent: !0 }, }, ]), result ); } function onSeriesTimerCancelled(result) { var instance = this.instance, itemId = this.itemId; return ( events.trigger(instance, "message", [ { MessageType: "SeriesTimerCancelled", Data: { Id: itemId, IsLocalEvent: !0 }, }, ]), result ); } function onPluginsUninstalled(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "PluginsUninstalled", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onUsersDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "UsersDeleted", Data: { Ids: [], IsLocalEvent: !0 } }, ]), result ); } function onUserNotificationsSaved(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "UserNotificationsSaved", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onUserNotificationsDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "UserNotificationsDeleted", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onScheduledTaskTriggersUpdated(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "ScheduledTaskTriggersUpdated", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onDevicesDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "DevicesDeleted", Data: { Ids: [], IsLocalEvent: !0 } }, ]), result ); } function onApiKeyCreated(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "ApiKeyCreated", Data: { Ids: [], IsLocalEvent: !0 } }, ]), result ); } function onApiKeysDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "ApiKeysDeleted", Data: { Ids: [], IsLocalEvent: !0 } }, ]), result ); } function onLiveTVGuideSourcesDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "LiveTVGuideSourcesDeleted", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onLiveTVTunerDevicesDeleted(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "LiveTVTunerDevicesDeleted", Data: { Ids: [], IsLocalEvent: !0 }, }, ]), result ); } function onItemsUpdated(result) { var instance = this.instance, itemIds = this.itemIds; return ( events.trigger(instance, "message", [ { MessageType: "LibraryChanged", Data: { ItemsAdded: [], ItemsRemoved: [], ItemsUpdated: itemIds, IsLocalEvent: !0, }, }, ]), result ); } function onItemUpdated(result) { var instance = this.instance, itemId = this.itemId; return ( events.trigger(instance, "message", [ { MessageType: "LibraryChanged", Data: { ItemsAdded: [], ItemsRemoved: [], ItemsUpdated: [itemId], IsLocalEvent: !0, }, }, ]), result ); } function onSyncJobCreated(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "SyncJobCreated", Data: { IsLocalEvent: !0 } }, ]), result ); } function onSyncJobCancelled(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "SyncJobCancelled", Data: { IsLocalEvent: !0 } }, ]), result ); } function onSyncJobItemCancelled(result) { var instance = this.instance; return ( events.trigger(instance, "message", [ { MessageType: "SyncJobItemCancelled", Data: { IsLocalEvent: !0 } }, ]), result ); } function onChannelManagementInfoUpdated(result) { var instance = this.instance, id = this.id; return ( events.trigger(instance, "message", [ { MessageType: "ChannelManagementInfoUpdated", Data: { Channel: result, Id: id, IsLocalEvent: !0 }, }, ]), result ); } function onChannelManagementSortIndexUpdated(result) { var instance = this.instance, id = this.id; return ( events.trigger(instance, "message", [ { MessageType: "ChannelManagementInfoUpdated", Data: { Id: id, IsLocalEvent: !0 }, }, ]), result ); } function onItemsDeleted(result) { var instance = this.instance, items = this.items, foldersRemovedFrom = [], itemsRemoved = []; for (let i = 0, length = items.length; i < length; i++) { var item = items[i]; item.ParentId && foldersRemovedFrom.push(item.ParentId), itemsRemoved.push(item.Id); } return ( events.trigger(instance, "message", [ { MessageType: "LibraryChanged", Data: { ItemsAdded: [], ItemsRemoved: itemsRemoved, ItemsUpdated: [], FoldersRemovedFrom: foldersRemovedFrom, IsLocalEvent: !0, }, }, ]), result ); } function onItemsMovedInPlaylist(result) { var instance = this.instance, playlistItemIds = this.playlistItemIds, playlistId = this.playlistId; return ( events.trigger(instance, "message", [ { MessageType: "ItemsMovedInPlaylist", Data: { PlaylistId: playlistId, PlaylistItemIds: playlistItemIds, IsLocalEvent: !0, }, }, ]), result ); } function onItemsRemovedFromPlaylist(result) { var instance = this.instance, playlistItemIds = this.playlistItemIds, playlistId = this.playlistId; return ( events.trigger(instance, "message", [ { MessageType: "ItemsRemovedFromPlaylist", Data: { PlaylistId: playlistId, PlaylistItemIds: playlistItemIds, IsLocalEvent: !0, }, }, ]), result ); } function onItemsRemovedFromCollection(result) { var instance = this.instance, itemIds = this.itemIds, collectionId = this.collectionId; return ( events.trigger(instance, "message", [ { MessageType: "ItemsRemovedFromCollection", Data: { CollectionId: collectionId, ItemIds: itemIds, IsLocalEvent: !0, }, }, ]), result ); } function getCachedWakeOnLanInfo(instance) { (instance = instance.serverId()), (instance = appStorage.getItem(`server-${instance}-wakeonlaninfo`)); return instance ? JSON.parse(instance) : []; } function refreshWakeOnLanInfoIfNeeded(instance) { !wakeOnLan.isSupported() || instance.isMinServerVersion("4.8.2") || (instance.serverVersion() && instance.isLoggedIn() && !1 !== instance.enableAutomaticBitrateDetection && (console.log("refreshWakeOnLanInfoIfNeeded"), setTimeout(refreshWakeOnLanInfo.bind(instance), 1e4))); } function refreshWakeOnLanInfo() { let instance = this; console.log("refreshWakeOnLanInfo"), instance.getWakeOnLanInfo().then( (info) => (onWakeOnLanInfoFetched(instance, info), info), (err) => (console.log("Error in getWakeOnLanInfo: " + (err || "")), []) ); } function onWakeOnLanInfoFetched(instance, info) { instance = instance.serverId(); appStorage.setItem(`server-${instance}-wakeonlaninfo`, JSON.stringify(info)); } function sendNextWakeOnLan(infos, index) { var info; return index >= infos.length ? Promise.resolve() : ((info = infos[index]), console.log("sending wakeonlan to " + info.MacAddress), wakeOnLan.send(info).then(goNext, goNext)); function goNext() { return sendNextWakeOnLan(infos, index + 1); } } function compareVersions(a, b) { (a = a.split(".")), (b = b.split(".")); for (let i = 0, length = Math.max(a.length, b.length); i < length; i++) { var aVal = parseInt(a[i] || "0"), bVal = parseInt(b[i] || "0"); if (aVal < bVal) return -1; if (bVal < aVal) return 1; } return 0; } function setScheduledTaskProperties(item, apiClient) { var serverId = apiClient.serverId(), triggers = ((item.Type = "ScheduledTask"), (item.ServerId = serverId), item.Triggers || []); for (let i = 0, length = triggers.length; i < length; i++) { var trigger = triggers[i]; (trigger.ScheduledTaskId = item.Id), (trigger.TriggerIndex = i), (trigger.TriggerType = trigger.Type), (trigger.Type = "ScheduledTaskTrigger"), (trigger.ServerId = serverId); } } function setDeviceProperies(item, apiClient) { (item.Type = "Device"), (item.ServerId = apiClient.serverId()), (item.PrimaryImageAspectRatio = 1); let iconUrl = item.IconUrl; iconUrl && -1 === iconUrl.indexOf("://") && (iconUrl = apiClient.getUrl(iconUrl)), (item.ImageUrl = iconUrl); } function updateTagItemsResponse(promise, query) { return promise.then(function (result) { let outerIds = query.OuterIds ? query.OuterIds.split(",") : []; return ( outerIds.length && (result.Items = result.Items.filter(function (i) { return outerIds.includes(i.Id); })), result.TotalRecordCount || !1 === query.EnableTotalRecordCount || (result.TotalRecordCount = result.Items.length), result ); }); } function getUrl(name, params, serverAddress) { if (!name) throw new Error("Url name cannot be empty"); let url = serverAddress || this._serverAddress; if (url) return ( (serverAddress = (url = url.endsWith("/") ? url.substring(0, url.length - 1) : url).toLowerCase()).endsWith("/emby") || serverAddress.endsWith("/mediabrowser") || (url += "/emby"), name && (name.startsWith("/") || (url += "/"), (url += name)), (params = params && queryString.paramsToString(params)) && (url += "?" + params), url ); throw new Error("serverAddress is yet not set"); } let StandardWidths = [480, 720, 1280, 1920, 2560, 3840]; class ApiClient { constructor( serverAddress, appName, appVersion, deviceName, deviceId, devicePixelRatio ) { if (!serverAddress) throw new Error("Must supply a serverAddress"); if (!appName) throw new Error("Must supply a appName"); if (!appVersion) throw new Error("Must supply a appVersion"); if (!deviceName) throw new Error("Must supply a deviceName"); if (!deviceId) throw new Error("Must supply a deviceId"); console.log("ApiClient serverAddress: " + serverAddress), console.log("ApiClient appName: " + appName), console.log("ApiClient appVersion: " + appVersion), console.log("ApiClient deviceName: " + deviceName), console.log("ApiClient deviceId: " + deviceId), (this._serverInfo = {}), (this._userAuthInfo = {}), (this._serverAddress = serverAddress), (this._deviceId = deviceId), (this._deviceName = deviceName), (this._appName = appName), (this._appVersion = appVersion), (this._devicePixelRatio = devicePixelRatio); } appName() { return this._appName; } setAuthorizationInfoIntoRequest(request, includeAccessToken) { var authValues = {}, appName = this._appName, includeAccessToken = (appName && (authValues["X-Emby-Client"] = appName), this._deviceName && (authValues["X-Emby-Device-Name"] = this._deviceName), this._deviceId && (authValues["X-Emby-Device-Id"] = this._deviceId), this._appVersion && (authValues["X-Emby-Client-Version"] = this._appVersion), !1 !== includeAccessToken && (appName = this.accessToken()) && (authValues["X-Emby-Token"] = appName), this.getCurrentLocale()), appName = (includeAccessToken && (authValues["X-Emby-Language"] = includeAccessToken), new URLSearchParams(authValues).toString()); if (appName) { let url = request.url; (url = url + (url.includes("?") ? "&" : "?") + appName), (request.url = url); } } appVersion() { return this._appVersion; } deviceName() { return this._deviceName; } deviceId() { return this._deviceId; } serverAddress(val) { if (null != val) { if (!val.toLowerCase().startsWith("http")) throw new Error("Invalid url: " + val); setServerAddress(this, val), onNetworkChanged(this); } return this._serverAddress; } onNetworkChanged() { onNetworkChanged(this, !0); } fetchWithFailover(request, enableReconnection, signal) { console.log("apiclient.fetchWithFailover " + request.url), (request.timeout = 3e4); let instance = this; return getFetchPromise(this, request, signal).then( (response) => ( (instance.connected = !0), response.status < 400 ? "json" === request.dataType || "application/json" === request.headers.accept ? response.json() : "text" === request.dataType || (response.headers.get("Content-Type") || "") .toLowerCase() .startsWith("text/") || 204 === response.status ? response.text() : response : Promise.reject(response) ), (error) => { if ( (error ? "AbortError" === error.name ? console.log("AbortError: " + request.url) : console.log( `Request failed to ${request.url} ${error.status || ""} ` + error.toString() ) : console.log("Request timed out to " + request.url), (error && error.status) || !enableReconnection) ) throw (console.log("Reporting request failure"), error); { console.log("Attempting reconnection"); let previousServerAddress = instance.serverAddress(); return tryReconnect(instance, signal, null).then( (newServerAddress) => ( console.log("Reconnect succeeded to " + newServerAddress), (instance.connected = !0), instance.enableWebSocketAutoConnect && instance.ensureWebSocket(), (request.url = request.url.replace( previousServerAddress, newServerAddress )), console.log("Retrying request with new url: " + request.url), instance.fetchWithFailover(request, !1, signal) ) ); } } ); } fetch(request, includeAccessToken, signal) { if (request) return ( (request.headers = request.headers || {}), this.setAuthorizationInfoIntoRequest(request, includeAccessToken), !1 === this.enableAutomaticNetworking || "GET" !== request.type ? getFetchPromise(this, request, signal).then((response) => response.status < 400 ? "json" === request.dataType || "application/json" === request.headers.accept ? response.json() : "text" === request.dataType || (response.headers.get("Content-Type") || "") .toLowerCase() .startsWith("text/") || 204 === response.status ? response.text() : response : Promise.reject(response) ) : this.fetchWithFailover(request, !0, signal) ); throw new Error("Request cannot be null"); } setAuthenticationInfo(userAuthInfo, allUsers) { this._userAuthInfo.UserId !== (userAuthInfo = userAuthInfo || {}).UserId && (this._userViewsPromise = null), (this._allUsers = allUsers || []), (this._userAuthInfo = userAuthInfo), refreshWakeOnLanInfoIfNeeded(this); } serverInfo(info) { var currentUserId; return ( info && ((currentUserId = this.getCurrentUserId()), (this._serverInfo = info), currentUserId !== this.getCurrentUserId()) && (this._userViewsPromise = null), this._serverInfo ); } getCurrentUserName() { var userId = this.getCurrentUserId(); return !userId || null == (userId = getCachedUser(this, userId)) ? null : userId.Name; } getCurrentUserId() { return this._userAuthInfo.UserId; } accessToken() { return this._userAuthInfo.AccessToken; } serverId() { return this.serverInfo().Id; } serverName() { return this.serverInfo().Name; } ajax(request, includeAccessToken) { if (request) return this.fetch(request, includeAccessToken, request.signal); throw new Error("Request cannot be null"); } getCurrentUser(options) { var userId = this.getCurrentUserId(); return userId ? this.getUser( userId, (options = options || {}).enableCache, options.signal ) : Promise.reject(); } isLoggedIn() { var info = this._userAuthInfo; return !!(info && info.UserId && info.AccessToken); } logout() { this.closeWebSocket(); var url, done = () => (this.clearAuthenticationInfo(), Promise.resolve()); return this.isLoggedIn() ? ((url = this.getUrl("Sessions/Logout")), this.ajax({ type: "POST", url: url, timeout: 1e4 }).then(done, done)) : done(); } authenticateUserByName(name, password) { if (!name) return Promise.reject(); var url = this.getUrl("Users/authenticatebyname"); let instance = this; return instance .ajax({ type: "POST", url: url, data: { Username: name, Pw: password || "" }, dataType: "json", }) .then((result) => { (instance._userViewsPromise = null), saveUserInCache(instance, result.User, !0); var afterOnAuthenticated = () => ( instance.getSystemInfo(), refreshWakeOnLanInfoIfNeeded(instance), result ); return instance.onAuthenticated ? instance .onAuthenticated(instance, result) .then(afterOnAuthenticated) : (afterOnAuthenticated(), result); }); } ensureWebSocket() { if ( this.connected && !this.isWebSocketOpenOrConnecting() && this.isWebSocketSupported() ) try { this.openWebSocket(); } catch (err) { console.log("Error opening web socket: " + (err || "")); } } openWebSocket() { var accessToken = this.accessToken(); if (!accessToken) throw new Error("Cannot open web socket without access token."); let serverUrl = this._serverAddress || ""; var hasSubdirectoryInServerAddress = (serverUrl = serverUrl.endsWith("/") ? serverUrl.substring(0, serverUrl.length - 1) : serverUrl) .toLowerCase() .endsWith("/emby"); let url; (url = hasSubdirectoryInServerAddress ? this.getUrl("embywebsocket") : replaceAll( (url = this.getUrl("socket")), "emby/socket", "embywebsocket" )), (url = replaceAll(url, "https:", "wss:")), (url = replaceAll(url, "http:", "ws:")), (url = (url += "?api_key=" + accessToken) + "&deviceId=" + this.deviceId()), console.log("opening web socket with url: " + url); hasSubdirectoryInServerAddress = new WebSocket(url); (hasSubdirectoryInServerAddress.onmessage = onWebSocketMessage.bind(this)), (hasSubdirectoryInServerAddress.onopen = onWebSocketOpen.bind(this)), (hasSubdirectoryInServerAddress.onerror = onWebSocketError.bind(this)), setSocketOnClose(this, hasSubdirectoryInServerAddress), (this._webSocket = hasSubdirectoryInServerAddress); } closeWebSocket() { var socket = this._webSocket; socket && socket.readyState === WebSocket.OPEN && socket.close(); } sendWebSocketMessage(name, data) { console.log("Sending web socket message: " + name); let msg = { MessageType: name }; data && (msg.Data = data), (msg = JSON.stringify(msg)), this._webSocket.send(msg); } startMessageListener(name, options) { console.log( `apiclient starting message listener ${name} with options ` + options ), this.sendMessage(name + "Start", options); let list = this.messageListeners; list || (this.messageListeners = list = []); for (let i = 0, length = list.length; i < length; i++) if (list[i].name === name) return; list.push({ name: name, options: options }); } stopMessageListener(name) { var list = this.messageListeners; list && (this.messageListeners = list.filter((n) => n.name !== name)), console.log("apiclient stopping message listener " + name), this.sendMessage(name + "Stop"); } sendMessage(name, data) { this.isWebSocketOpen() && this.sendWebSocketMessage(name, data); } isMessageChannelOpen() { return this.isWebSocketOpen(); } isWebSocketOpen() { var socket = this._webSocket; return !!socket && socket.readyState === WebSocket.OPEN; } isWebSocketOpenOrConnecting() { var socket = this._webSocket; return ( !!socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) ); } get(url) { return this.ajax({ type: "GET", url: url }); } getJSON(url, signal) { return this.fetch( { url: url, type: "GET", dataType: "json" }, null, signal ); } getText(url, signal) { return this.fetch( { url: url, type: "GET", dataType: "text" }, null, signal ); } updateServerInfo(server, serverUrl) { if (null == server) throw new Error("server cannot be null"); if ((this.serverInfo(server), !serverUrl)) throw new Error( "serverUrl cannot be null. serverInfo: " + JSON.stringify(server) ); console.log("Setting server address to " + serverUrl), this.serverAddress(serverUrl); } isWebSocketSupported() { try { return null != WebSocket; } catch (err) { return !1; } } clearAuthenticationInfo() { this.setAuthenticationInfo(null, null); } encodeName(name) { name = (name = (name = name.split("/").join("-")).split("&").join("-")) .split("?") .join("-"); name = new URLSearchParams({ name: name }).toString(); return name.substring(name.indexOf("=") + 1).replace("'", "%27"); } getProductNews(options = {}) { options = this.getUrl("News/Product", options); return this.getJSON(options); } detectBitrate(signal) { let instance = this; return this.getEndpointInfo(signal).then( (info) => detectBitrateWithEndpointInfo(instance, info), (err) => ( console.log("error in getEndpointInfo: " + (err || "")), detectBitrateWithEndpointInfo(instance, {}) ) ); } getItem(userId, itemId, options, signal) { var fields; if (itemId) return ( options?.fields && !appHost.supports("sync") && ((fields = removeItemAll( (fields = options.fields.split(",")), "SyncStatus" )), (fields = removeItemAll(fields, "ContainerSyncStatus")), (options.fields = fields.join(","))), (fields = userId ? this.getUrl(`Users/${userId}/Items/` + itemId, options) : this.getUrl("Items/" + itemId, options)), this.getJSON(fields, signal) ); throw new Error("null itemId"); } getRootFolder(userId) { if (userId) return ( (userId = this.getUrl(`Users/${userId}/Items/Root`)), this.getJSON(userId) ); throw new Error("null userId"); } getCurrentLocale() { return this.currentLocale; } setCurrentLocale(value) { this.currentLocale = value; } getNotificationTypes(options) { return this.getJSON( this.getUrl( "Notifications/Types", (options = "string" == typeof options ? {} : options) ) ); } sendTestUserNotification(options) { var url = this.getUrl("Notifications/Services/Test"); return this.ajax({ type: "POST", url: url, data: JSON.stringify(options), contentType: "application/json", }); } saveUserNotification(options) { var url = this.getUrl("Notifications/Services/Configured"); return this.ajax({ type: "POST", url: url, data: JSON.stringify(options), contentType: "application/json", }).then(onUserNotificationsSaved.bind({ instance: this, items: [] })); } deleteUserNotifications(items) { let instance = this; return Promise.all( items.map(function (item) { return instance.ajax({ url: instance.getUrl("Notifications/Services/Configured", { Id: item.Id, UserId: item.UserId, }), type: "DELETE", }); }) ).then( onUserNotificationsDeleted.bind({ instance: this, items: items }), onUserNotificationsDeleted.bind({ instance: this, items: items }) ); } getFeatures(query) { return this.isMinServerVersion("4.8.0.20") ? this.getJSON(this.getUrl("Features", query)) : Promise.resolve([]); } getRemoteImageProviders(options) { var urlPrefix; if (options) return ( (urlPrefix = getRemoteImagePrefix(this, options)), (urlPrefix = this.getUrl( urlPrefix + "/RemoteImages/Providers", options )), this.getJSON(urlPrefix) ); throw new Error("null options"); } getAvailableRemoteImages(options) { var urlPrefix; if (options) return ( (urlPrefix = getRemoteImagePrefix(this, options)), (urlPrefix = this.getUrl(urlPrefix + "/RemoteImages", options)), this.getJSON(urlPrefix) ); throw new Error("null options"); } downloadRemoteImage(options) { var itemId, urlPrefix; if (options) return ( (itemId = options.itemId), (urlPrefix = getRemoteImagePrefix(this, options)), (urlPrefix = this.getUrl( urlPrefix + "/RemoteImages/Download", options )), this.ajax({ type: "POST", url: urlPrefix }).then( onItemUpdated.bind({ instance: this, itemId: itemId }) ) ); throw new Error("null options"); } getRecordingFolders(userId) { userId = this.getUrl("LiveTv/Recordings/Folders", { userId: userId }); return this.getJSON(userId); } getLiveTvInfo(options) { options = this.getUrl("LiveTv/Info", options || {}); return this.getJSON(options); } getLiveTvGuideInfo(options) { options = this.getUrl("LiveTv/GuideInfo", options || {}); return this.getJSON(options); } getLiveTvChannel(id, userId) { var options; if (id) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("LiveTv/Channels/" + id, options)), this.getJSON(userId) ); throw new Error("null id"); } getLiveTvChannelsForManagement(query) { query = this.getUrl("LiveTv/Manage/Channels", query); return this.getJSON(query); } setChannelDisabled(item, disabled) { var id = item.Id, item = this.getUrl(`LiveTv/Manage/Channels/${id}/Disabled`, { ManagementId: item.ManagementId, Disabled: disabled, }); return this.ajax({ type: "POST", url: item, contentType: "application/json", dataType: "json", }).then(onChannelManagementInfoUpdated.bind({ instance: this, id: id })); } setChannelSortIndex(item, newIndex) { var id = item.Id, item = this.getUrl(`LiveTv/Manage/Channels/${id}/SortIndex`, { ManagementId: item.ManagementId, NewIndex: newIndex, }); return this.ajax({ type: "POST", url: item }).then( onChannelManagementSortIndexUpdated.bind({ instance: this, id: id }) ); } getLiveTvChannels(options) { options = this.getUrl("LiveTv/Channels", options || {}); return this.getJSON(options); } getLiveTvPrograms(options = {}) { return options.channelIds && 1800 < options.channelIds.length ? this.ajax({ type: "POST", url: this.getUrl("LiveTv/Programs"), data: JSON.stringify(options), contentType: "application/json", dataType: "json", }) : this.getJSON(this.getUrl("LiveTv/Programs", options)); } getEpg(options = {}) { return ( (options.AddCurrentProgram = !1), (options.EnableUserData = !1), (options.EnableImageTypes = "Primary"), (options.UserId = this.getCurrentUserId()), 0 !== options.Limit || this.isMinServerVersion("4.8.0.46") || (options.Limit = 1), this.getJSON(this.getUrl("LiveTv/EPG", options)).then( modifyEpgResponse.bind(this) ) ); } getLiveTvRecommendedPrograms(options = {}) { return this.getJSON(this.getUrl("LiveTv/Programs/Recommended", options)); } getLiveTvRecordings(options, signal) { options = this.getUrl("LiveTv/Recordings", options || {}); return this.getJSON(options, signal); } getLiveTvRecordingSeries(options) { options = this.getUrl("LiveTv/Recordings/Series", options || {}); return this.getJSON(options); } getLiveTvRecording(id, userId) { var options; if (id) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("LiveTv/Recordings/" + id, options)), this.getJSON(userId) ); throw new Error("null id"); } getLiveTvProgram(id, userId) { var options; if (id) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("LiveTv/Programs/" + id, options)), this.getJSON(userId) ); throw new Error("null id"); } cancelLiveTvTimer(id) { if (id) return ( (id = this.getUrl(`LiveTv/Timers/${id}/Delete`)), this.ajax({ type: "POST", url: id }) ); throw new Error("null id"); } getLiveTvTimers(options) { options = this.getUrl("LiveTv/Timers", options || {}); return this.getJSON(options); } getLiveTvTimer(id) { if (id) return (id = this.getUrl("LiveTv/Timers/" + id)), this.getJSON(id); throw new Error("null id"); } getNewLiveTvTimerDefaults(options = {}) { options = this.getUrl("LiveTv/Timers/Defaults", options); return this.getJSON(options); } createLiveTvTimer(item) { var url; if (item) return ( (url = this.getUrl("LiveTv/Timers")), this.ajax({ type: "POST", url: url, data: JSON.stringify(item), contentType: "application/json", }) ); throw new Error("null item"); } updateLiveTvTimer(item) { var url; if (item) return ( (url = this.getUrl("LiveTv/Timers/" + item.Id)), this.ajax({ type: "POST", url: url, data: JSON.stringify(item), contentType: "application/json", }) ); throw new Error("null item"); } resetLiveTvTuner(id) { if (id) return ( (id = this.getUrl(`LiveTv/Tuners/${id}/Reset`)), this.ajax({ type: "POST", url: id }) ); throw new Error("null id"); } getLiveTvSeriesTimers(query, signal) { return this.getJSON(this.getUrl("LiveTv/SeriesTimers", query), signal); } getLiveTvSeriesTimer(id) { if (id) return (id = this.getUrl("LiveTv/SeriesTimers/" + id)), this.getJSON(id); throw new Error("null id"); } cancelLiveTvSeriesTimer(id) { var url; if (id) return ( (url = this.getUrl(`LiveTv/SeriesTimers/${id}/Delete`)), this.ajax({ type: "POST", url: url }).then( onSeriesTimerCancelled.bind({ instance: this, itemId: id }) ) ); throw new Error("null id"); } createLiveTvSeriesTimer(item) { var url; if (item) return ( (url = this.getUrl("LiveTv/SeriesTimers")), this.ajax({ type: "POST", url: url, dataType: this.isMinServerVersion("4.9.0.13") ? "json" : null, data: JSON.stringify(item), contentType: "application/json", }).then(onSeriesTimerCreated.bind({ instance: this })) ); throw new Error("null item"); } updateLiveTvSeriesTimer(item) { var itemId, url; if (item) return ( (itemId = item.Id), (url = this.getUrl("LiveTv/SeriesTimers/" + itemId)), this.ajax({ type: "POST", url: url, data: JSON.stringify(item), contentType: "application/json", }).then(onSeriesTimerUpdated.bind({ instance: this, itemId: itemId })) ); throw new Error("null item"); } getRegistrationInfo(feature) { feature = this.getUrl("Registrations/" + feature); return this.getJSON(feature); } getSystemInfo() { var url = this.getUrl("System/Info"); let instance = this; return this.getJSON(url).then( (info) => (instance.setSystemInfo(info), Promise.resolve(info)) ); } getSyncStatus(item) { return isLocalId(item.Id) ? Promise.resolve({}) : item.SyncStatus || this.isMinServerVersion("4.8.0.53") ? Promise.resolve({ Status: item.SyncStatus }) : ((item = this.getUrl(`Sync/${item.Id}/Status`)), this.ajax({ url: item, type: "POST", dataType: "json", contentType: "application/json", data: JSON.stringify({ TargetId: this.deviceId() }), })); } getPublicSystemInfo() { var url = this.getUrl("System/Info/Public"); let instance = this; return this.getJSON(url).then( (info) => (instance.setSystemInfo(info), Promise.resolve(info)) ); } getInstantMixFromItem(itemId, options) { return isLocalId(itemId) ? Promise.resolve({ Items: [], TotalRecordCount: 0 }) : ((itemId = this.getUrl(`Items/${itemId}/InstantMix`, options)), this.getJSON(itemId)); } getEpisodes(itemId, options, signal) { let requiresStartItemIdPostProcess = !1; (options = options || {}).SeasonId || !options.StartItemId || this.isMinServerVersion("4.8.0.29") || ((options.Limit = null), (requiresStartItemIdPostProcess = !0)); (itemId = this.getUrl(`Shows/${itemId}/Episodes`, options)), (itemId = this.getJSON(itemId, signal)); return requiresStartItemIdPostProcess ? itemId.then(function (result) { let index = -1; for (let i = 0, length = result.Items.length; i < length; i++) if (options.StartItemId === result.Items[i].Id) { index = i; break; } return ( -1 !== index && ((result.Items = result.Items.slice(index)), !1 !== options.EnableTotalRecordCount) && (result.TotalRecordCount = result.Items.length), result ); }) : itemId; } getDisplayPreferences(userId) { let instance = this; return instance.isMinServerVersion("4.9.0.23") ? instance.getJSON(instance.getUrl("usersettings/" + userId)) : this.getJSON( this.getUrl("DisplayPreferences/usersettings", { userId: userId, client: "emby", }) ).then(function (result) { return ( (instance._displayPreferencesId = result.Id), result.CustomPrefs || {} ); }); } updatePartialDisplayPreferences(obj, userId) { if (this.isMinServerVersion("4.9.0.23")) return this.ajax({ type: "POST", url: this.getUrl("usersettings/" + userId + "/Partial"), data: JSON.stringify(obj), contentType: "application/json", }); throw new Error("unsupported server version"); } updateDisplayPreferences(obj, userId) { return this.isMinServerVersion("4.9.0.23") ? this.ajax({ type: "POST", url: this.getUrl("usersettings/" + userId), data: obj, contentType: "application/json", }) : this.ajax({ type: "POST", url: this.getUrl("DisplayPreferences/usersettings", { userId: userId, client: "emby", }), data: JSON.stringify({ CustomPrefs: obj, Client: "emby", Id: this._displayPreferencesId || "3ce5b65de116d73165d1efc4a30ec35c", }), contentType: "application/json", }); } getSeasons(itemId, options) { itemId = this.getUrl(`Shows/${itemId}/Seasons`, options); return this.getJSON(itemId); } getSimilarItems(itemId, options) { return isLocalId(itemId) ? Promise.resolve({ Items: [], TotalRecordCount: 0 }) : ((itemId = this.getUrl(`Items/${itemId}/Similar`, options)), this.getJSON(itemId)); } getCultures() { var url = this.getUrl("Localization/cultures"); return this.getJSON(url); } getCountries() { var url = this.getUrl("Localization/countries"); return this.getJSON(url); } getPlaybackInfo(itemId, options, deviceProfile, signal) { deviceProfile = { DeviceProfile: deviceProfile }; return this.ajax({ url: this.getUrl(`Items/${itemId}/PlaybackInfo`, options), type: "POST", data: JSON.stringify(deviceProfile), contentType: "application/json", dataType: "json", signal: signal, }); } getLiveStreamMediaInfo(liveStreamId) { liveStreamId = { LiveStreamId: liveStreamId }; return this.ajax({ url: this.getUrl("LiveStreams/MediaInfo"), type: "POST", data: JSON.stringify(liveStreamId), contentType: "application/json", dataType: "json", }); } getIntros(itemId, signal) { return isLocalId(itemId) ? Promise.resolve({ Items: [], TotalRecordCount: 0 }) : this.getJSON( this.getUrl( `Users/${this.getCurrentUserId()}/Items/${itemId}/Intros` ), signal ); } getDirectoryContents(path, options) { if (!path) throw new Error("null path"); if ("string" != typeof path) throw new Error("invalid path"); return ( ((options = options || {}).path = path), this.isMinServerVersion("4.8.0.53") ? this.ajax({ type: "POST", data: JSON.stringify(options), contentType: "application/json", dataType: "json", url: this.getUrl("Environment/DirectoryContents"), }) : this.getJSON(this.getUrl("Environment/DirectoryContents", options)) ); } getNetworkShares(path) { var options; if (path) return ( ((options = {}).path = path), (path = this.getUrl("Environment/NetworkShares", options)), this.getJSON(path) ); throw new Error("null path"); } getParentPath(path) { var options; if (path) return ( ((options = {}).path = path), (path = this.getUrl("Environment/ParentPath", options)), this.ajax({ type: "GET", url: path, dataType: "text" }) ); throw new Error("null path"); } getDrives() { var url = this.getUrl("Environment/Drives"); return this.getJSON(url); } getNetworkDevices() { var url = this.getUrl("Environment/NetworkDevices"); return this.getJSON(url); } getActivityLog(options) { options = this.getUrl("System/ActivityLog/Entries", options || {}); let serverId = this.serverId(); return this.getJSON(options).then((result) => { var items = result.Items; for (let i = 0, length = items.length; i < length; i++) { var item = items[i]; (item.Type = "ActivityLogEntry"), (item.ServerId = serverId); } return result; }); } cancelPackageInstallation(installationId) { if (installationId) return ( (installationId = this.getUrl( `Packages/Installing/${installationId}/Delete` )), this.ajax({ type: "POST", url: installationId }) ); throw new Error("null installationId"); } refreshItems(items, options) { if (!items) throw new Error("null items"); let instance = this; return Promise.all( items.map(function (item) { return instance.ajax({ type: "POST", url: instance.getUrl(`Items/${item.Id}/Refresh`, options), }); }) ); } installPlugin(name, guid, updateClass, version) { if (!name) throw new Error("null name"); if (updateClass) return ( (updateClass = { updateClass: updateClass, AssemblyGuid: guid }), version && (updateClass.version = version), (guid = this.getUrl("Packages/Installed/" + name, updateClass)), this.ajax({ type: "POST", url: guid }) ); throw new Error("null updateClass"); } restartServer() { var url = this.getUrl("System/Restart"); return this.ajax({ type: "POST", url: url }); } shutdownServer() { var url = this.getUrl("System/Shutdown"); return this.ajax({ type: "POST", url: url }); } getPackageInfo(name, guid) { if (name) return ( (name = this.getUrl("Packages/" + name, { AssemblyGuid: guid })), this.getJSON(name) ); throw new Error("null name"); } getAvailableApplicationUpdate() { var url = this.getUrl("Packages/Updates", { PackageType: "System" }); return this.getJSON(url); } getAvailablePluginUpdates() { var url = this.getUrl("Packages/Updates", { PackageType: "UserInstalled" }); return this.getJSON(url); } getVirtualFolders(query, signal) { let serverId = this.serverId(); return this.getJSON( this.getUrl( "Library/VirtualFolders/Query", (query = "string" == typeof query ? { userId: query } : query) ), signal ).then(function (result) { for (let i = 0, length = result.Items.length; i < length; i++) { var item = result.Items[i]; mapVirtualFolder(item), (item.ServerId = serverId); } return result; }); } getPhysicalPaths() { var url = this.getUrl("Library/PhysicalPaths"); return this.getJSON(url); } getServerConfiguration() { var url = this.getUrl("System/Configuration"); return this.getJSON(url); } getDevices(query) { let instance = this; return this.getJSON(this.getUrl("Devices", query)).then(function (result) { for (let i = 0, length = result.Items.length; i < length; i++) setDeviceProperies(result.Items[i], instance); return result; }); } getDevicesOptions() { var url = this.getUrl("System/Configuration/devices"); return this.getJSON(url); } getContentUploadHistory() { var url = this.getUrl("Devices/CameraUploads", { DeviceId: this.deviceId(), }); return this.getJSON(url); } getNamedConfiguration(name) { name = this.getUrl("System/Configuration/" + name); return this.getJSON(name); } getHardwareAccelerations() { var url = this.getUrl("Encoding/HardwareAccelerations"); return this.getJSON(url); } getVideoCodecInformation() { var url = this.getUrl("Encoding/CodecInformation/Video"); return this.getJSON(url); } getScheduledTasks(options = {}) { options = this.getUrl("ScheduledTasks", options); let instance = this; return this.getJSON(options).then(function (result) { for (let i = 0, length = result.length; i < length; i++) setScheduledTaskProperties(result[i], instance); return result; }); } startScheduledTask(id) { if (id) return ( (id = this.getUrl("ScheduledTasks/Running/" + id)), this.ajax({ type: "POST", url: id }) ); throw new Error("null id"); } getScheduledTask(id) { if (!id) throw new Error("null id"); let instance = this; id = this.getUrl("ScheduledTasks/" + id); return this.getJSON(id).then(function (result) { return setScheduledTaskProperties(result, instance), result; }); } getNextUpAudioBookItems(options, signal) { return options.AlbumId && isLocalId(options.AlbumId) ? Promise.resolve({ Items: [], TotalRecordCount: 0 }) : ((options = this.getUrl("AudioBooks/NextUp", options)), this.getJSON(options, signal)); } getNextUpEpisodes(options, signal) { return options.SeriesId && isLocalId(options.SeriesId) ? Promise.resolve({ Items: [], TotalRecordCount: 0 }) : ((options = this.getUrl("Shows/NextUp", options)), this.getJSON(options, signal)); } stopScheduledTask(id) { if (id) return ( (id = this.getUrl(`ScheduledTasks/Running/${id}/Delete`)), this.ajax({ type: "POST", url: id }) ); throw new Error("null id"); } getPluginConfiguration(id) { if (id) return ( (id = this.getUrl(`Plugins/${id}/Configuration`)), this.getJSON(id) ); throw new Error("null Id"); } getAvailablePlugins(options = {}) { options.PackageType = "UserInstalled"; options = this.getUrl("Packages", options); return this.getJSON(options); } uninstallPlugin(id) { if (id) return this.uninstallPlugins([{ Id: id }]); throw new Error("null Id"); } uninstallPluginSingle(id) { if (id) return ( (id = this.getUrl(`Plugins/${id}/Delete`)), this.ajax({ type: "POST", url: id }) ); throw new Error("null Id"); } uninstallPlugins(items) { return Promise.all( items.map(mapToId).map(this.uninstallPluginSingle.bind(this)) ).then(onPluginsUninstalled.bind({ instance: this, items: items })); } removeVirtualFolder(virtualFolder, refreshLibrary) { if (!virtualFolder) throw new Error("null virtualFolder"); let instance = this; var id = virtualFolder.Id, refreshLibrary = this.getUrl("Library/VirtualFolders/Delete", { refreshLibrary: !!refreshLibrary, id: id, name: virtualFolder.Name, }); return this.ajax({ type: "POST", url: refreshLibrary }) .then(onItemsDeleted.bind({ instance: this, items: [virtualFolder] })) .then(() => { instance._userViewsPromise = null; }); } addVirtualFolder(name, type, refreshLibrary, libraryOptions) { if (!name) throw new Error("null name"); var options = {}, type = (type && (options.collectionType = type), (options.refreshLibrary = !!refreshLibrary), (options.name = name), this.getUrl("Library/VirtualFolders", options)); let instance = this; return this.ajax({ type: "POST", url: type, data: JSON.stringify({ LibraryOptions: libraryOptions }), contentType: "application/json", }).then(() => { instance._userViewsPromise = null; }); } updateVirtualFolderOptions(id, libraryOptions) { if (!id) throw new Error("null name"); var url = this.getUrl("Library/VirtualFolders/LibraryOptions"); let instance = this; return this.ajax({ type: "POST", url: url, data: JSON.stringify({ Id: id, LibraryOptions: libraryOptions }), contentType: "application/json", }) .then(onItemUpdated.bind({ instance: this, itemId: id })) .then(() => { instance._userViewsPromise = null; }); } renameVirtualFolder(virtualFolder, newName, refreshLibrary) { if (!virtualFolder) throw new Error("null virtualFolder"); refreshLibrary = this.getUrl("Library/VirtualFolders/Name", { refreshLibrary: !!refreshLibrary, newName: newName, name: virtualFolder.Name, Id: virtualFolder.Id, }); let instance = this; return this.ajax({ type: "POST", url: refreshLibrary }) .then(onItemUpdated.bind({ instance: this, itemId: virtualFolder.Id })) .then(() => { instance._userViewsPromise = null; }); } addMediaPath(virtualFolder, pathInfo, refreshLibrary) { if (!virtualFolder) throw new Error("null virtualFolder"); if (!pathInfo) throw new Error("null pathInfo"); refreshLibrary = this.getUrl("Library/VirtualFolders/Paths", { refreshLibrary: !!refreshLibrary, }); let instance = this; return this.ajax({ type: "POST", url: refreshLibrary, data: JSON.stringify({ Name: virtualFolder.Name, PathInfo: pathInfo, Id: virtualFolder.Id, }), contentType: "application/json", }).then(() => { instance._userViewsPromise = null; }); } updateMediaPath(virtualFolder, pathInfo) { if (!virtualFolder) throw new Error("null virtualFolder"); if (!pathInfo) throw new Error("null pathInfo"); var url = this.getUrl("Library/VirtualFolders/Paths/Update"); let instance = this; return this.ajax({ type: "POST", url: url, data: JSON.stringify({ Name: virtualFolder.Name, PathInfo: pathInfo, Id: virtualFolder.Id, }), contentType: "application/json", }).then(() => { instance._userViewsPromise = null; }); } removeMediaPath(virtualFolder, mediaPath, refreshLibrary) { if (!virtualFolder) throw new Error("null virtualFolder"); if (!mediaPath) throw new Error("null mediaPath"); let instance = this; refreshLibrary = this.getUrl("Library/VirtualFolders/Paths/Delete", { refreshLibrary: !!refreshLibrary, path: mediaPath, name: virtualFolder.Name, Id: virtualFolder.Id, }); return this.ajax({ type: "POST", url: refreshLibrary }).then(() => { instance._userViewsPromise = null; }); } deleteUserSingle(id) { if (!id) throw new Error("null id"); let serverId = this.serverId(), instance = this; var url = this.getUrl(`Users/${id}/Delete`); return this.ajax({ type: "POST", url: url }).then(() => { removeCachedUser(id, serverId), (instance._userViewsPromise = null); }); } deleteUsers(items) { return Promise.all( items.map(mapToId).map(this.deleteUserSingle.bind(this)) ).then(onUsersDeleted.bind({ instance: this, items: items })); } deleteUser(id) { return this.deleteUser([{ Id: id }]); } deleteUserImage(userId, imageType, imageIndex) { if (!userId) throw new Error("null userId"); if (!imageType) throw new Error("null imageType"); let url = this.getUrl(`Users/${userId}/Images/` + imageType), instance = (null != imageIndex && (url += "/" + imageIndex), this); return ( (url += "/Delete"), this.ajax({ type: "POST", url: url }).then(() => updateCachedUser(instance, userId) ) ); } deleteItemImage(itemId, imageType, imageIndex) { if (!imageType) throw new Error("null imageType"); let url = this.getUrl(`Items/${itemId}/Images`); (url += "/" + imageType), null != imageIndex && (url += "/" + imageIndex); return ( (url += "/Delete"), this.ajax({ type: "POST", url: url }).then( onItemUpdated.bind({ instance: this, itemId: itemId }) ) ); } deleteItems(items) { return this.deleteItemsInternal(items).then( onItemsDeleted.bind({ instance: this, items: items }) ); } deleteItemsInternal(items) { if (items) return ( (items = items.map(mapToId).filter(isNotLocalId)), this.ajax({ type: "POST", url: this.getUrl("Items/Delete", { Ids: items.join(",") }), }) ); throw new Error("null itemId"); } stopActiveEncodings(playSessionId) { var options = { deviceId: this.deviceId() }, playSessionId = (playSessionId && (options.PlaySessionId = playSessionId), this.getUrl("Videos/ActiveEncodings/Delete", options)); return this.ajax({ type: "POST", url: playSessionId }); } reportCapabilities(options) { var url = this.getUrl("Sessions/Capabilities/Full"); return this.ajax({ type: "POST", url: url, data: JSON.stringify(options), contentType: "application/json", }); } updateItemImageFromUrl(itemId, imageType, imageIndex, imageUrl) { if (imageType) return this.ajax({ type: "POST", url: this.getUrl( `Items/${itemId}/Images/${imageType}/${(imageIndex = imageIndex || 0)}/Url`, {} ), data: JSON.stringify({ Url: imageUrl }), contentType: "application/json", }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); throw new Error("null imageType"); } updateItemImageIndex(itemId, imageType, imageIndex, newIndex) { if (imageType) return ( (imageType = this.getUrl( `Items/${itemId}/Images/${imageType}/${(imageIndex = imageIndex || 0)}/Index`, { newIndex: newIndex } )), this.ajax({ type: "POST", url: imageType }).then( onItemUpdated.bind({ instance: this, itemId: itemId }) ) ); throw new Error("null imageType"); } getItemImageInfos(itemId) { itemId = this.getUrl(`Items/${itemId}/Images`); return this.getJSON(itemId); } getCriticReviews(itemId, options) { if (itemId) return ( (itemId = this.getUrl(`Items/${itemId}/CriticReviews`, options)), this.getJSON(itemId) ); throw new Error("null itemId"); } getItemDownloadUrl(itemId, mediaSourceId, serverAddress) { if (itemId) return this.getUrl( `Items/${itemId}/Download`, { api_key: this.accessToken(), mediaSourceId: mediaSourceId }, serverAddress ); throw new Error("itemId cannot be empty"); } getSessions(options) { options = this.getUrl("Sessions", options); return this.getJSON(options); } uploadUserImage(userId, imageType, file) { if (!userId) throw new Error("null userId"); if (!imageType) throw new Error("null imageType"); if (!file) throw new Error("File must be an image."); if ( "image/png" !== file.type && "image/jpeg" !== file.type && "image/jpeg" !== file.type ) throw new Error("File must be an image."); let instance = this; return new Promise((resolve, reject) => { var reader = new FileReader(); (reader.onerror = () => { reject(); }), (reader.onabort = () => { reject(); }), (reader.onload = ({ target }) => { var target = target.result.split(",")[1], url = instance.getUrl(`Users/${userId}/Images/` + imageType); instance .ajax({ type: "POST", url: url, data: target, contentType: "image/" + file.name.substring(file.name.lastIndexOf(".") + 1), }) .then(() => { updateCachedUser(instance, userId).then(resolve, reject); }, reject); }), reader.readAsDataURL(file); }); } uploadItemImage(itemId, imageType, imageIndex, file) { if (!itemId) throw new Error("null itemId"); if (!imageType) throw new Error("null imageType"); if (!file) throw new Error("File must be an image."); if ( "image/png" !== file.type && "image/jpeg" !== file.type && "image/jpeg" !== file.type ) throw new Error("File must be an image."); let url = this.getUrl(`Items/${itemId}/Images`), instance = ((url += "/" + imageType), this); return ( null != imageIndex && (url += "?Index=" + imageIndex), new Promise((resolve, reject) => { var reader = new FileReader(); (reader.onerror = () => { reject(); }), (reader.onabort = () => { reject(); }), (reader.onload = ({ target }) => { target = target.result.split(",")[1]; instance .ajax({ type: "POST", url: url, data: target, contentType: "image/" + file.name.substring(file.name.lastIndexOf(".") + 1), }) .then(function (result) { onItemUpdated.call({ instance: instance, itemId: itemId }), resolve(result); }, reject); }), reader.readAsDataURL(file); }) ); } getInstalledPlugins() { var url = this.getUrl("Plugins", {}); return this.getJSON(url); } getCurrentUserCached() { return getCachedUser(this, this.getCurrentUserId()); } getUser(id, enableCache, signal) { if (!id) throw new Error("Must supply a userId"); let cachedUser; if ( !1 !== enableCache && (cachedUser = getCachedUser(this, id)) && Date.now() - (cachedUser.DateLastFetched || 0) <= 6e4 ) return Promise.resolve(cachedUser); let instance = this; var url = this.getUrl("Users/" + id), url = this.getJSON(url, signal).then( (user) => (saveUserInCache(instance, user), user), (response) => { if ( (!signal || !signal.aborted) && (!response || !response.status) && instance.isLoggedIn() ) { var user = getCachedUser(instance, id); if (user) return Promise.resolve(user); } throw response; } ); return !1 !== enableCache && cachedUser ? Promise.resolve(cachedUser) : url; } getStudio(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("Studios/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getGenre(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("Genres/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getMusicGenre(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("MusicGenres/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getGameGenre(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("GameGenres/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getArtist(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("Artists/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getPerson(name, userId) { var options; if (name) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl("Persons/" + this.encodeName(name), options)), this.getJSON(userId) ); throw new Error("null name"); } getPublicUsersQueryResult(query, signal) { let serverId = this.serverId(); var url = this.getUrl("users/public"); return this.ajax( { type: "GET", url: url, dataType: "json", signal: signal }, !1 ) .then(function (users) { return setUsersProperties(users, serverId), users; }) .then(function (users) { var totalRecordCount = users.length; return ( query && ((users = users.slice(query.StartIndex || 0)), query.Limit) && users.length > query.Limit && (users.length = query.Limit), { Items: users, TotalRecordCount: totalRecordCount } ); }); } getPublicUsers() { return this.getPublicUsersQueryResult({}).then(function (result) { return result.Items; }); } getUsersQueryResult(query, signal) { let serverId = this.serverId(); return this.getJSON(this.getUrl("Users/Query", query), signal).then( function (result) { return setUsersProperties(result.Items, serverId), result; } ); } getUsersForItemAccess(query, signal) { let serverId = this.serverId(); return this.getJSON(this.getUrl("Users/ItemAccess", query), signal).then( function (result) { return setUsersProperties(result.Items, serverId), result; } ); } getUsers(query, signal) { return this.getUsersQueryResult(query, signal).then(function (result) { return result.Items; }); } getUserPrefixes(query, signal) { return this.getJSON(this.getUrl("Users/Prefixes", query), signal); } getApiKeys(query, signal) { let instance = this; return this.getJSON(this.getUrl("Auth/Keys", query), signal).then(function ( result ) { return setApiKeysProperties(instance, result), result; }); } getLogs(query, signal) { let instance = this; return this.getJSON(this.getUrl("System/Logs/Query", query), signal).then( function (result) { return setLogsProperties(instance, result.Items), result; } ); } getLogDownloadUrl({ Name, Sanitize, SetFilename }) { return this.getUrl("System/Logs/" + Name, { Sanitize: Sanitize, api_key: this.accessToken(), SetFilename: SetFilename, }); } getLogLines(options, signal) { var name = options.name, name = ((options.name = null), this.getUrl(`System/Logs/${name}/Lines`, options || {})); return this.getJSON(name, signal); } getParentalRatings() { var url = this.getUrl("Localization/ParentalRatings"); return this.getJSON(url); } getDefaultImageSizes() { return StandardWidths.slice(0); } getImageUrls(itemId, imageOptions, sourceOptions) { var sources = [], originalImageOptions = imageOptions, widths = sourceOptions?.widths || StandardWidths; for (let i = 0, length = widths.length; i < length; i++) ((imageOptions = Object.assign( {}, originalImageOptions )).adjustForPixelRatio = !1), (imageOptions.maxWidth = widths[i]), sources.push({ url: this.getImageUrl(itemId, imageOptions), width: imageOptions.maxWidth, }); return sources; } getImageUrl(itemId, options) { if (!itemId) throw new Error("itemId cannot be empty"); let url = `Items/${itemId}/Images/` + (options = options || {}).type; return ( null != options.index && (url += "/" + options.index), normalizeImageOptions(this, options), delete options.type, delete options.index, this.getUrl(url, options) ); } getLogoImageUrl(item, options, preferredLogoImageTypes) { for ( let i = 0, length = (preferredLogoImageTypes = preferredLogoImageTypes || [ "LogoLightColor", "LogoLight", "Logo", ]).length; i < length; i++ ) { var logoType = preferredLogoImageTypes[i]; if (item.ImageTags && item.ImageTags[logoType]) return ( (options.type = logoType), (options.tag = item.ImageTags[logoType]), this.getImageUrl(item.Id, options) ); } return item.ParentLogoImageTag ? ((options.tag = item.ParentLogoImageTag), (options.type = "Logo"), this.getImageUrl(item.ParentLogoItemId, options)) : ("TvChannel" === item.Type || "ChannelManagementInfo" === item.Type) && item.ImageTags && item.ImageTags.Primary ? ((options.tag = item.ImageTags.Primary), (options.type = "Primary"), this.getImageUrl(item.Id, options)) : null; } getUserImageUrl(userId, options) { if (!userId) throw new Error("null userId"); let url = `Users/${userId}/Images/` + (options = options || {}).type; return ( null != options.index && (url += "/" + options.index), normalizeImageOptions(this, options), delete options.type, delete options.index, this.getUrl(url, options) ); } getThumbImageUrl(item, options) { if (item) return ( ((options = options || {}).imageType = "thumb"), item.ImageTags && item.ImageTags.Thumb ? ((options.tag = item.ImageTags.Thumb), this.getImageUrl(item.Id, options)) : item.ParentThumbItemId ? ((options.tag = item.ImageTags.ParentThumbImageTag), this.getImageUrl(item.ParentThumbItemId, options)) : null ); throw new Error("null item"); } updateUserPassword(userId, currentPassword, newPassword) { if (!userId) return Promise.reject(); var url = this.getUrl(`Users/${userId}/Password`); let instance = this; return this.ajax({ type: "POST", url: url, data: { CurrentPw: currentPassword || "", NewPw: newPassword }, }).then(() => updateCachedUser(instance, userId)); } updateProfilePin(userId, pin) { return this.updatePartialUserConfiguration(userId, { ProfilePin: pin || null, }); } updateEasyPassword(userId, newPassword) { let instance = this; var url; return !instance.isMinServerVersion("4.8.0.40") && userId ? ((url = this.getUrl(`Users/${userId}/EasyPassword`)), this.ajax({ type: "POST", url: url, data: { NewPw: newPassword }, }).then(() => updateCachedUser(instance, userId))) : Promise.reject(); } resetUserPassword(userId) { if (!userId) throw new Error("null userId"); var url = this.getUrl(`Users/${userId}/Password`); let instance = this; var postData = { resetPassword: !0 }; return this.ajax({ type: "POST", url: url, data: postData }).then(() => updateCachedUser(instance, userId) ); } resetEasyPassword(userId) { if (!userId) throw new Error("null userId"); var url = this.getUrl(`Users/${userId}/EasyPassword`); let instance = this; var postData = { resetPassword: !0 }; return this.ajax({ type: "POST", url: url, data: postData }).then(() => updateCachedUser(instance, userId) ); } updateServerConfiguration(configuration) { var url; if (configuration) return ( (url = this.getUrl("System/Configuration")), this.ajax({ type: "POST", url: url, data: JSON.stringify(configuration), contentType: "application/json", }) ); throw new Error("null configuration"); } updatePartialServerConfiguration(configuration) { let instance = this; if (!instance.isMinServerVersion("4.8.8")) return instance .getServerConfiguration() .then(function (serverConfiguration) { return ( (serverConfiguration = Object.assign( serverConfiguration, configuration )), instance.updateServerConfiguration(serverConfiguration) ); }); var url; if (configuration) return ( (url = this.getUrl("System/Configuration/Partial")), this.ajax({ type: "POST", url: url, data: JSON.stringify(configuration), contentType: "application/json", }) ); throw new Error("null configuration"); } updateNamedConfiguration(name, configuration) { if (configuration) return ( (name = this.getUrl("System/Configuration/" + name)), this.ajax({ type: "POST", url: name, data: JSON.stringify(configuration), contentType: "application/json", }) ); throw new Error("null configuration"); } getTypedUserSettings(userId, key) { userId = this.getUrl(`Users/${userId}/TypedSettings/` + key); return this.getJSON(userId); } updateTypedUserSettings(userId, key, configuration) { if (configuration) return ( (userId = this.getUrl(`Users/${userId}/TypedSettings/` + key)), this.ajax({ type: "POST", url: userId, data: JSON.stringify(configuration), contentType: "application/json", }) ); throw new Error("null configuration"); } getTunerHostConfiguration(id) { return this.getNamedConfiguration("livetv").then(function (config) { return config.TunerHosts.filter(function (i) { return i.Id === id; })[0]; }); } saveTunerHostConfiguration(tunerHostInfo) { return this.ajax({ type: "POST", url: this.getUrl("LiveTv/TunerHosts"), data: JSON.stringify(tunerHostInfo), contentType: "application/json", dataType: "json", }); } getDefaultTunerHostConfiguration(type) { return this.getJSON(this.getUrl("LiveTv/TunerHosts/Default/" + type)); } updateItem(item) { var url; if (item) return ( (url = this.getUrl("Items/" + item.Id)), this.ajax({ type: "POST", url: url, data: JSON.stringify(item), contentType: "application/json", }).then(onItemUpdated.bind({ instance: this, itemId: item.Id })) ); throw new Error("null item"); } updatePluginSecurityInfo(info) { var url = this.getUrl("Plugins/SecurityInfo"); return this.ajax({ type: "POST", url: url, data: JSON.stringify(info), contentType: "application/json", }); } createUser(options) { var url = this.getUrl("Users/New"); return this.ajax({ type: "POST", url: url, data: options, dataType: "json", }); } updateUser(user) { var url; if (user) return ( (url = this.getUrl("Users/" + user.Id)), this.ajax({ type: "POST", url: url, data: JSON.stringify(user), contentType: "application/json", }) ); throw new Error("null user"); } updateUserPolicy(userId, policy) { if (!userId) throw new Error("null userId"); if (!policy) throw new Error("null policy"); var url = this.getUrl(`Users/${userId}/Policy`); let instance = this; return this.ajax({ type: "POST", url: url, data: JSON.stringify(policy), contentType: "application/json", }).then( () => ( instance.getCurrentUserId() === userId && (instance._userViewsPromise = null), updateCachedUser(instance, userId) ) ); } updateUserConfiguration(userId, configuration) { if (!userId) throw new Error("null userId"); if (!configuration) throw new Error("null configuration"); var url = this.getUrl(`Users/${userId}/Configuration`); let instance = this; return this.ajax({ type: "POST", url: url, data: JSON.stringify(configuration), contentType: "application/json", }).then( () => ( instance.getCurrentUserId() === userId && (instance._userViewsPromise = null), updateCachedUser(instance, userId) ) ); } updatePartialUserConfiguration(userId, configuration) { let instance = this; if (!instance.isMinServerVersion("4.8.0.48")) return instance.getUser(userId).then(function (user) { return ( (user.Configuration = Object.assign( user.Configuration, configuration )), instance.updateUserConfiguration(userId, user.Configuration) ); }); if (!userId) throw new Error("null userId"); var url; if (configuration) return ( (url = this.getUrl(`Users/${userId}/Configuration/Partial`)), this.ajax({ type: "POST", url: url, data: JSON.stringify(configuration), contentType: "application/json", }).then( () => ( instance.getCurrentUserId() === userId && (instance._userViewsPromise = null), updateCachedUserConfig(instance, userId, configuration) ) ) ); throw new Error("null configuration"); } updateScheduledTaskTriggers(id, triggers) { if (!id) throw new Error("null id"); if (!triggers) throw new Error("null triggers"); for ( let i = 0, length = (triggers = JSON.parse(JSON.stringify(triggers))).length; i < length; i++ ) { var trigger = triggers[i]; trigger.TriggerType && (trigger.Type = trigger.TriggerType); } id = this.getUrl(`ScheduledTasks/${id}/Triggers`); return this.ajax({ type: "POST", url: id, data: JSON.stringify(triggers), contentType: "application/json", }).then( onScheduledTaskTriggersUpdated.bind({ instance: this, items: triggers }) ); } updatePluginConfiguration(id, configuration) { if (!id) throw new Error("null Id"); if (configuration) return ( (id = this.getUrl(`Plugins/${id}/Configuration`)), this.ajax({ type: "POST", url: id, data: JSON.stringify(configuration), contentType: "application/json", }) ); throw new Error("null configuration"); } getAncestorItems(itemId, userId) { var options; if (itemId) return ( (options = {}), userId && (options.userId = userId), (userId = this.getUrl(`Items/${itemId}/Ancestors`, options)), this.getJSON(userId) ); throw new Error("null itemId"); } getItems(userId, options, signal) { if ( options && null != options.IsNewOrPremiere && !this.isMinServerVersion("4.8.0.48") ) return Promise.resolve({ Items: [], TotalRecordCount: 0 }); let url; return ( (url = "string" === (typeof userId).toString().toLowerCase() ? this.getUrl(`Users/${userId}/Items`, options) : this.getUrl("Items", options)), this.getJSON(url, signal) ); } getLiveTvChannelTags(options, signal) { (options = options || {}).UserId = this.getCurrentUserId(); options = this.getUrl("LiveTv/ChannelTags", options); return this.getJSON(options, signal); } getLiveTvChannelTagPrefixes(options, signal) { (options = options || {}).UserId = this.getCurrentUserId(); options = this.getUrl("LiveTv/ChannelTags/Prefixes", options); return this.getJSON(options, signal); } getResumableItems(userId, options, signal) { return this.getJSON( this.getUrl(`Users/${userId}/Items/Resume`, options), signal ); } getMovieRecommendations(options, signal) { return this.getJSON(this.getUrl("Movies/Recommendations", options), signal); } getUpcomingEpisodes(options, signal) { return this.getJSON(this.getUrl("Shows/Upcoming", options), signal); } getMissingEpisodes(options, signal) { return this.isMinServerVersion("4.8.0.59") ? this.getJSON(this.getUrl("Shows/Missing", options), signal) : Promise.resolve({ Items: [], TotalRecordCount: 0 }); } getUserViews(options, userId, signal) { var currentUserId = this.getCurrentUserId(), currentUserId = !( (userId = userId || currentUserId) !== currentUserId || (options && options.IncludeHidden) ); if (currentUserId && this._userViewsPromise) return this._userViewsPromise; userId = this.getUrl(`Users/${userId}/Views`, options); let self = this; options = this.getJSON(userId, signal).catch( (err) => ((self._userViewsPromise = null), Promise.reject(err)) ); return currentUserId && (this._userViewsPromise = options), options; } getArtists(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Artists", options); return this.getJSON(userId); } getAlbumArtists(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Artists/AlbumArtists", options); return this.getJSON(userId); } getGenres(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Genres", options); return this.getJSON(userId); } getMusicGenres(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("MusicGenres", options); return this.getJSON(userId); } getGameGenres(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("GameGenres", options); return this.getJSON(userId); } getPeople(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Persons", options); return this.getJSON(userId); } getThumbnails(itemId, options) { return isLocalId(itemId) ? Promise.resolve({ Thumbnails: [] }) : ((itemId = this.getUrl(`Items/${itemId}/ThumbnailSet`, options)), this.getJSON(itemId)); } getDeleteInfo(itemId, options) { return isLocalId(itemId) ? Promise.resolve({ Paths: [] }) : ((itemId = this.getUrl(`Items/${itemId}/DeleteInfo`, options)), this.getJSON(itemId)); } getStudios(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Studios", options); return this.getJSON(userId); } getOfficialRatings(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("OfficialRatings", options); return this.getJSON(userId); } getYears(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Years", options); return this.getJSON(userId); } getTags(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; (userId = this.getUrl("Tags", options)), (options = this.getJSON(userId)), (userId = fillTagProperties.bind(this)); return options.then(userId); } getItemTypes(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("ItemTypes", options); return this.getJSON(userId); } getContainers(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Containers", options); return this.getJSON(userId); } getAudioCodecs(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("AudioCodecs", options); return this.getJSON(userId); } getAudioLayouts(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; (userId = this.getUrl("AudioLayouts", options)), (userId = this.getJSON(userId)); return this.isMinServerVersion("4.8.0.23") ? userId : updateTagItemsResponse(userId, options); } getStreamLanguages(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("StreamLanguages", options); return this.getJSON(userId); } getVideoCodecs(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("VideoCodecs", options); return this.getJSON(userId); } getExtendedVideoTypes(userId, options) { if (!this.isMinServerVersion("4.8.0.47")) return Promise.resolve({ Items: [], TotalRecordCount: 0 }); if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("ExtendedVideoTypes", options); return this.getJSON(userId); } getSubtitleCodecs(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("SubtitleCodecs", options); return this.getJSON(userId); } getPrefixes(userId, options) { if (userId) return ( ((options = options || {}).userId = userId), isLocalId(options.ParentId) || isLocalId(options.GenreIds) || isLocalId(options.ArtistIds) || isLocalId(options.StudioIds) ? Promise.resolve([]) : ((userId = this.getUrl("Items/Prefixes", options)), this.getJSON(userId)) ); throw new Error("null userId"); } getArtistPrefixes(userId, options) { if (!userId) throw new Error("null userId"); (options = options || {}).userId = userId; userId = this.getUrl("Artists/Prefixes", options); return this.getJSON(userId); } getLocalTrailers(userId, itemId) { if (!userId) throw new Error("null userId"); if (itemId) return ( (userId = this.getUrl(`Users/${userId}/Items/${itemId}/LocalTrailers`)), this.getJSON(userId) ); throw new Error("null itemId"); } getAllTrailers(query, item) { return ( item.LocalTrailerCount && !1 !== query.LocalTrailers ? this.getLocalTrailers(this.getCurrentUserId(), item.Id) : Promise.resolve([]) ).then(function (localTrailers) { let trailers = localTrailers.splice(0); if (item.RemoteTrailers && !1 !== query.RemoteTrailers) for (let i = 0, length = item.RemoteTrailers.length; i < length; i++) trailers.push(item.RemoteTrailers[i]); localTrailers = (((item.MediaSources || [])[0] || {}).MediaStreams || []).filter( function (i) { return "Video" === i.Type; } )[0] || {}; let aspect = null; localTrailers.Width && localTrailers.Height && (aspect = localTrailers.Width / localTrailers.Height); for (let i = 0, length = trailers.length; i < length; i++) { var trailer = trailers[i]; trailer.Name || (trailer.Name = "Trailer: " + item.Name), trailer.Type || (trailer.Type = "Trailer"), trailer.ServerId || (trailer.ServerId = item.ServerId), trailer.MediaType || (trailer.MediaType = "Video"), trailer.PrimaryImageAspectRatio || (trailer.PrimaryImageAspectRatio = aspect), (trailer.ImageTags && trailer.ImageTags.Thumb) || (item.ImageTags && item.ImageTags.Thumb ? ((trailer.ParentThumbItemId = item.Id), (trailer.ParentThumbImageTag = item.ImageTags.Thumb)) : ((trailer.ParentThumbItemId = item.ParentThumbItemId), (trailer.ParentThumbImageTag = item.ParentThumbImageTag))), (trailer.ParentBackdropImageTags && trailer.ParentBackdropImageTags.length) || ((trailer.ParentBackdropItemId = item.Id), (trailer.ParentBackdropImageTags = item.BackdropImageTags)); } localTrailers = trailers.length; return ( query && ((trailers = trailers.slice(query.StartIndex || 0)), query.Limit) && trailers.length > query.Limit && (trailers.length = query.Limit), Promise.resolve({ Items: trailers, TotalRecordCount: localTrailers }) ); }); } getGameSystems() { var options = {}, userId = this.getCurrentUserId(), userId = (userId && (options.userId = userId), this.getUrl("Games/SystemSummaries", options)); return this.getJSON(userId); } getAdditionalVideoParts(userId, itemId) { var options; if (itemId) return isLocalId(itemId) ? Promise.resolve([]) : ((options = {}), userId && (options.userId = userId), (userId = this.getUrl(`Videos/${itemId}/AdditionalParts`, options)), this.getJSON(userId)); throw new Error("null itemId"); } getThemeMedia(itemId, options) { return isLocalId(itemId) ? Promise.resolve({ ThemeVideosResult: { Items: [], TotalRecordCount: 0 }, ThemeSongsResult: { Items: [], TotalRecordCount: 0 }, }) : ((itemId = this.getUrl(`Items/${itemId}/ThemeMedia`, options)), this.getJSON(itemId)); } getAudioStreamUrl( { Id }, { Container, Protocol, AudioCodec }, directPlayContainers, maxBitrate, maxAudioSampleRate, maxAudioBitDepth, startPosition, enableRemoteMedia ) { Id = `Audio/${Id}/universal`; return ( startingPlaySession++, this.getUrl(Id, { UserId: this.getCurrentUserId(), DeviceId: this.deviceId(), MaxStreamingBitrate: maxBitrate, Container: directPlayContainers, TranscodingContainer: Container || null, TranscodingProtocol: Protocol || null, AudioCodec: AudioCodec, MaxAudioSampleRate: maxAudioSampleRate, MaxAudioBitDepth: maxAudioBitDepth, api_key: this.accessToken(), PlaySessionId: startingPlaySession, StartTimeTicks: startPosition || 0, EnableRedirection: !0, EnableRemoteMedia: enableRemoteMedia, }) ); } getAudioStreamUrls( items, transcodingProfile, directPlayContainers, maxBitrate, maxAudioSampleRate, maxAudioBitDepth, startPosition, enableRemoteMedia ) { var streamUrls = []; for (let i = 0, length = items.length; i < length; i++) { var item = items[i]; let streamUrl; "Audio" === item.MediaType && (streamUrl = this.getAudioStreamUrl( item, transcodingProfile, directPlayContainers, maxBitrate, maxAudioSampleRate, maxAudioBitDepth, startPosition, enableRemoteMedia )), streamUrls.push(streamUrl || ""), 0 === i && (startPosition = 0); } return Promise.resolve(streamUrls); } getSpecialFeatures(userId, itemId, options) { if (!userId) throw new Error("null userId"); if (itemId) return isLocalId(itemId) ? Promise.resolve([]) : ((userId = this.getUrl( `Users/${userId}/Items/${itemId}/SpecialFeatures`, options )), this.getJSON(userId)); throw new Error("null itemId"); } getDateParamValue(date) { function formatDigit(i) { return i < 10 ? "0" + i : i; } return ( "" + date.getFullYear() + formatDigit(date.getMonth() + 1) + formatDigit(date.getDate()) + formatDigit(date.getHours()) + formatDigit(date.getMinutes()) + formatDigit(date.getSeconds()) ); } markPlayed(userId, itemIds, date) { if (!userId) throw new Error("null userId"); if (!itemIds) throw new Error("null itemIds"); let instance = this; return ( (itemIds = itemIds.filter(isNotLocalId)), Promise.all( itemIds.map(function (itemId) { var options = {}, options = (date && (options.DatePlayed = instance.getDateParamValue(date)), instance.getUrl( `Users/${userId}/PlayedItems/` + itemId, options )); return instance .ajax({ type: "POST", url: options, dataType: "json" }) .then( onUserDataUpdated.bind({ instance: instance, userId: userId, itemId: itemId, }) ); }) ) ); } markUnplayed(userId, itemIds) { if (!userId) throw new Error("null userId"); if (!itemIds) throw new Error("null itemIds"); let instance = this; return ( (itemIds = itemIds.filter(isNotLocalId)), Promise.all( itemIds.map(function (itemId) { var url = instance.getUrl( `Users/${userId}/PlayedItems/${itemId}/Delete` ); return instance .ajax({ type: "POST", url: url, dataType: "json" }) .then( onUserDataUpdated.bind({ instance: instance, userId: userId, itemId: itemId, }) ); }) ) ); } updateFavoriteStatus(userId, itemIds, isFavorite) { if (!userId) throw new Error("null userId"); if (!itemIds) throw new Error("null itemIds"); let instance = this; return ( (itemIds = itemIds.filter(isNotLocalId)), Promise.all( itemIds.map(function (itemId) { let url; return ( (url = isFavorite ? instance.getUrl(`Users/${userId}/FavoriteItems/` + itemId) : instance.getUrl( `Users/${userId}/FavoriteItems/${itemId}/Delete` )), instance .ajax({ type: "POST", url: url, dataType: "json" }) .then( onUserDataUpdated.bind({ instance: instance, userId: userId, itemId: itemId, }) ) ); }) ) ); } updateUserItemRating(userId, itemId, likes) { if (!userId) throw new Error("null userId"); if (itemId) return ( (likes = this.getUrl(`Users/${userId}/Items/${itemId}/Rating`, { likes: likes, })), this.ajax({ type: "POST", url: likes, dataType: "json" }).then( onUserDataUpdated.bind({ instance: this, userId: userId, itemId: itemId, }) ) ); throw new Error("null itemId"); } updateHideFromResume(itemIds, hide) { if (!itemIds) throw new Error("null itemIds"); let userId = this.getCurrentUserId(), instance = this; return Promise.all( itemIds.map(function (itemId) { var url = instance.getUrl( `Users/${userId}/Items/${itemId}/HideFromResume`, { Hide: !1 !== hide } ); return instance .ajax({ type: "POST", url: url, dataType: "json" }) .then( onUserDataUpdated.bind({ instance: instance, userId: userId, itemId: itemId, }) ); }) ); } getItemCounts(userId) { var options = {}, userId = (userId && (options.userId = userId), this.getUrl("Items/Counts", options)); return this.getJSON(userId); } clearUserItemRating(userId, itemId) { if (!userId) throw new Error("null userId"); var url; if (itemId) return ( (url = this.getUrl(`Users/${userId}/Items/${itemId}/Rating/Delete`)), this.ajax({ type: "POST", url: url, dataType: "json" }).then( onUserDataUpdated.bind({ instance: this, userId: userId, itemId: itemId, }) ) ); throw new Error("null itemId"); } reportPlaybackStart(options) { if (!options) throw new Error("null options"); (this.lastPlaybackProgressReport = 0), (this.lastPlaybackProgressReportTicks = null); var url = this.getUrl("Sessions/Playing"), url = this.ajax({ type: "POST", data: JSON.stringify(options), contentType: "application/json", url: url, }); return ( options.ItemId && !isLocalId(options.ItemId) && this.ensureWebSocket(), url ); } shouldSkipProgressReport(eventName, positionTicks) { if ("timeupdate" === (eventName || "timeupdate")) { eventName = Date.now() - (this.lastPlaybackProgressReport || 0); if (eventName <= 1e4) { if (!positionTicks) return Promise.resolve(); eventName = 1e4 * eventName + (this.lastPlaybackProgressReportTicks || 0); if (Math.abs((positionTicks || 0) - eventName) < 5e7) return Promise.resolve(); } } return !1; } reportPlaybackProgress(options) { if (!options) throw new Error("null options"); var newPositionTicks = options.PositionTicks; if ("timeupdate" === (options.EventName || "timeupdate")) { var now = Date.now(), msSinceLastReport = now - (this.lastPlaybackProgressReport || 0); if (msSinceLastReport <= 1e4) { if (!newPositionTicks) return Promise.resolve(); msSinceLastReport = 1e4 * msSinceLastReport + (this.lastPlaybackProgressReportTicks || 0); if (Math.abs((newPositionTicks || 0) - msSinceLastReport) < 5e7) return Promise.resolve(); } this.lastPlaybackProgressReport = now; } else this.lastPlaybackProgressReport = 0; this.lastPlaybackProgressReportTicks = newPositionTicks; msSinceLastReport = this.getUrl("Sessions/Playing/Progress"); return this.ajax({ type: "POST", data: JSON.stringify(options), contentType: "application/json", url: msSinceLastReport, }); } reportOfflineActions(actions) { var url; if (actions) return ( (url = this.getUrl("Sync/OfflineActions")), this.ajax({ type: "POST", data: JSON.stringify(actions), contentType: "application/json", url: url, }) ); throw new Error("null actions"); } syncData(data) { var url; if (data) return ( (url = this.getUrl("Sync/Data")), this.ajax({ type: "POST", data: JSON.stringify(data), contentType: "application/json", url: url, dataType: "json", }) ); throw new Error("null data"); } getReadySyncItems(deviceId) { if (deviceId) return ( (deviceId = this.getUrl("Sync/Items/Ready", { TargetId: deviceId })), this.getJSON(deviceId) ); throw new Error("null deviceId"); } getSyncJobs(query) { let instance = this, mode = query.mode; return ( delete query.mode, instance .getJSON(instance.getUrl("Sync/Jobs", query)) .then(function (result) { var items = result.Items; for (let i = 0, length = items.length; i < length; i++) { var item = items[i]; (item.SyncJobType = "convert" === mode ? "Convert" : "Download"), setSyncJobProperties(item, instance); } return result; }) ); } createSyncJob(options) { return this.ajax({ type: "POST", url: this.getUrl("Sync/Jobs"), data: JSON.stringify(options), contentType: "application/json", dataType: "json", }).then(onSyncJobCreated.bind({ instance: this })); } reportSyncJobItemTransferred(syncJobItemId) { if (syncJobItemId) return ( (syncJobItemId = this.getUrl( `Sync/JobItems/${syncJobItemId}/Transferred` )), this.ajax({ type: "POST", url: syncJobItemId }) ); throw new Error("null syncJobItemId"); } cancelSyncItems(itemIds, targetId) { if (itemIds) return ( (targetId = `Sync/${targetId || this.deviceId()}/Items/Delete`), this.ajax({ type: "POST", url: this.getUrl(targetId, { ItemIds: itemIds.join(",") }), }) ); throw new Error("null itemIds"); } clearUserTrackSelections(userId, type) { if (!userId) throw new Error("null userId"); let instance = this; type = this.getUrl(`Users/${userId}/TrackSelections/${type}/Delete`); return this.ajax({ type: "POST", url: type }).then(() => updateCachedUser(instance, userId) ); } reportPlaybackStopped(options) { if (!options) throw new Error("null options"); (this.lastPlaybackProgressReport = 0), (this.lastPlaybackProgressReportTicks = null); var url = this.getUrl("Sessions/Playing/Stopped"); return this.ajax({ type: "POST", data: JSON.stringify(options), contentType: "application/json", url: url, }); } sendPlayCommand(sessionId, options) { if (!sessionId) throw new Error("null sessionId"); if (options) return ( (sessionId = this.getUrl(`Sessions/${sessionId}/Playing`, options)), this.ajax({ type: "POST", url: sessionId }) ); throw new Error("null options"); } sendCommand(sessionId, command) { if (!sessionId) throw new Error("null sessionId"); if (command) return ( ((sessionId = { type: "POST", url: this.getUrl(`Sessions/${sessionId}/Command`), }).data = JSON.stringify(command)), (sessionId.contentType = "application/json"), this.ajax(sessionId) ); throw new Error("null command"); } sendMessageCommand(sessionId, options) { if (!sessionId) throw new Error("null sessionId"); if (options) return ( ((sessionId = { type: "POST", url: this.getUrl(`Sessions/${sessionId}/Message`), }).data = JSON.stringify(options)), (sessionId.contentType = "application/json"), this.ajax(sessionId) ); throw new Error("null options"); } sendPlayStateCommand(sessionId, command, options) { if (!sessionId) throw new Error("null sessionId"); if (command) return ( (sessionId = this.getUrl( `Sessions/${sessionId}/Playing/` + command, options || {} )), this.ajax({ type: "POST", url: sessionId }) ); throw new Error("null command"); } getSavedEndpointInfo() { return this._endPointInfo; } getEndpointInfo(signal) { var savedValue = this._endPointInfo; if (savedValue) return Promise.resolve(savedValue); let instance = this; return this.getJSON(this.getUrl("System/Endpoint"), signal).then( (endPointInfo) => ( setSavedEndpointInfo(instance, endPointInfo), endPointInfo ) ); } getWakeOnLanInfo() { return this.getJSON(this.getUrl("System/WakeOnLanInfo")); } getLatestItems(options = {}) { return this.getJSON( this.getUrl(`Users/${this.getCurrentUserId()}/Items/Latest`, options) ); } getPlayQueue(options) { return this.getJSON(this.getUrl("Sessions/PlayQueue", options)); } supportsWakeOnLan() { return !!wakeOnLan.isSupported() && 0 < getCachedWakeOnLanInfo(this).length; } wakeOnLan() { return sendNextWakeOnLan(getCachedWakeOnLanInfo(this), 0); } getAddToPlaylistInfo(userId, id, addIds) { return this.isMinServerVersion("4.8.0.30") ? ((id = this.getUrl("Playlists/" + id + "/AddToPlaylistInfo", { Ids: addIds, userId: userId, })), this.getJSON(id)) : Promise.resolve({ ContainsDuplicates: !1, ItemCount: addIds.length }); } addToList(userId, type, id, addIds, skipDuplicates) { var id = this.getUrl( ("BoxSet" === type || "Collection" === type ? "Collections" : "Playlists") + "/" + id + "/Items" ), dataType = "Playlist" === type && this.isMinServerVersion("4.8.0.30") ? "json" : null; return this.ajax({ type: "POST", url: id, dataType: dataType, data: JSON.stringify({ Ids: addIds.join(","), userId: userId, SkipDuplicates: "Playlist" === type ? skipDuplicates : null, }), contentType: "application/json", }).then(function (result) { return ( null == (result = result || {}).ItemAddedCount && (result.ItemAddedCount = addIds.length), Promise.resolve(result) ); }); } createList(userId, type, name, addIds) { type = this.getUrl( "BoxSet" === type || "Collection" === type ? "Collections" : "Playlists", { Name: name, Ids: addIds, userId: userId } ); return this.ajax({ type: "POST", url: type, dataType: "json" }).then( function (result) { return ( null == (result = result || {}).ItemAddedCount && (result.ItemAddedCount = (addIds || []).length), Promise.resolve(result) ); } ); } setSystemInfo(systemInfo) { null != systemInfo.HasImageEnhancers && (this.hasImageEnhancers = systemInfo.HasImageEnhancers), systemInfo.WakeOnLanInfo && onWakeOnLanInfoFetched(this, systemInfo.WakeOnLanInfo), (this._serverVersion = systemInfo.Version); } refreshSystemInfo() {} serverVersion() { return this._serverVersion; } isMinServerVersion(version) { var serverVersion = this.serverVersion(); return !!serverVersion && 0 <= compareVersions(serverVersion, version); } handleMessageReceived(msg) { onMessageReceivedInternal(this, msg); } getSearchResults(query) { var promises; return !query.SearchTerm || query.SearchTerm.length < 1 ? Promise.resolve({ Items: [], TotalRecordCount: 0, ItemTypes: [] }) : ((promises = []).push(this.getItems(this.getCurrentUserId(), query)), query.StartIndex || query.IncludeItemTypes || !1 === query.IncludeSearchTypes || promises.push(this.getItemTypes(this.getCurrentUserId(), query)), Promise.all(promises).then(function (responses) { return ( 1 < responses.length && (responses[0].ItemTypes = responses[1].Items), responses[0] ); })); } getToneMapOptions() { var url = this.getUrl("Encoding/ToneMapOptions"); return this.getJSON(url); } moveItemsInPlaylist(playlistId, items, newIndex) { var playlistItemIds = []; for (let i = 0, length = items.length; i < length; i++) items[i].PlaylistItemId && playlistItemIds.push(items[i].PlaylistItemId); var playlistItemId = items[0].PlaylistItemId; return this.ajax({ url: this.getUrl( "Playlists/" + playlistId + "/Items/" + playlistItemId + "/Move/" + newIndex ), type: "POST", }).then( onItemsMovedInPlaylist.bind({ instance: this, playlistItemIds: playlistItemIds, playlistId: playlistId, }) ); } removeItemsFromPlaylist(playlistId, items) { var playlistItemIds = []; for (let i = 0, length = items.length; i < length; i++) items[i].PlaylistItemId && playlistItemIds.push(items[i].PlaylistItemId); return this.ajax({ url: this.getUrl("Playlists/" + playlistId + "/Items/Delete", { EntryIds: playlistItemIds.join(","), }), type: "POST", }).then( onItemsRemovedFromPlaylist.bind({ instance: this, playlistItemIds: playlistItemIds, playlistId: playlistId, }) ); } removeItemsFromCollection(collectionId, items) { var itemIds = []; for (let i = 0, length = items.length; i < length; i++) itemIds.push(items[i].Id); return this.ajax({ url: this.getUrl("Collections/" + collectionId + "/Items/Delete", { Ids: itemIds.join(","), }), type: "POST", }).then( onItemsRemovedFromCollection.bind({ instance: this, itemIds: itemIds, collectionId: collectionId, }) ); } reconnectTest(signal) { return tryReconnect(this, signal); } mergeVersions(items) { let instance = this; return this.ajax({ type: "POST", url: this.getUrl("Videos/MergeVersions", { Ids: items.map(mapToId).join(","), }), }).then(function (result) { return ( events.trigger(instance, "message", [ { MessageType: "ItemsMerged", Data: { Items: items.map(mapToId), IsLocalEvent: !0 }, }, ]), result ); }); } ungroupVersions(id) { let instance = this; return instance .ajax({ type: "POST", url: instance.getUrl("Videos/" + id + "/AlternateSources/Delete"), }) .then(function (result) { return ( events.trigger(instance, "message", [ { MessageType: "ItemsSplit", Data: { Items: [id], IsLocalEvent: !0 }, }, ]), result ); }); } makePublic(itemId) { return this.ajax({ type: "POST", url: this.getUrl("Items/" + itemId + "/MakePublic"), }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); } makePrivate(itemId) { return this.ajax({ type: "POST", url: this.getUrl("Items/" + itemId + "/MakePrivate"), }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); } updateUserItemAccess(options) { return this.ajax({ type: "POST", url: this.getUrl("Items/Access"), data: JSON.stringify(options), contentType: "application/json", }); } leaveSharedItems(options) { return this.ajax({ type: "POST", url: this.getUrl("Items/Shared/Leave"), data: JSON.stringify(options), contentType: "application/json", }).then( onItemsDeleted.bind({ instance: this, items: options.ItemIds.map(function (i) { return { Id: i }; }), }) ); } downloadSubtitles(itemId, mediaSourceId, id) { return this.ajax({ type: "POST", url: this.getUrl("Items/" + itemId + "/RemoteSearch/Subtitles/" + id, { MediaSourceId: mediaSourceId, }), dataType: "json", }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); } resetMetadata(options) { return this.ajax({ type: "POST", url: this.getUrl("items/metadata/reset"), data: JSON.stringify(options), contentType: "application/json", }).then( onItemsUpdated.bind({ instance: this, itemIds: options.ItemIds.split(","), }) ); } applyRemoteSearchResult(itemId, searchResult, options) { return this.ajax({ type: "POST", url: this.getUrl("Items/RemoteSearch/Apply/" + itemId, options), data: JSON.stringify(searchResult), contentType: "application/json", }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); } deleteSubtitles(itemId, mediaSourceId, subtitleStreamIndex) { return this.ajax({ type: "POST", url: this.getUrl( "Videos/" + itemId + "/Subtitles/" + subtitleStreamIndex + "/Delete", { MediaSourceId: mediaSourceId } ), }).then(onItemUpdated.bind({ instance: this, itemId: itemId })); } cancelSyncJobs(ids) { let instance = this; return Promise.all( ids.map(function (id) { return instance.ajax({ url: instance.getUrl("Sync/Jobs/" + id + "/Delete"), type: "POST", }); }) ).then(onSyncJobCancelled.bind({ instance: this })); } cancelSyncJobItems(ids) { let instance = this; return Promise.all( ids.map(function (id) { return instance.ajax({ url: instance.getUrl("Sync/JobItems/" + id + "/Delete"), type: "POST", }); }) ).then(onSyncJobItemCancelled.bind({ instance: this })); } removeEmbyConnectLink(userId) { return this.ajax({ type: "POST", url: this.getUrl("Users/" + userId + "/Connect/Link/Delete"), }); } createApiKey(options) { return this.ajax({ type: "POST", url: this.getUrl("Auth/Keys", options), }).then(onApiKeyCreated.bind({ instance: this })); } deleteApiKeySingle(accessToken) { return this.ajax({ type: "POST", url: this.getUrl("Auth/Keys/" + accessToken + "/Delete"), }); } deleteApiKeys(items) { return Promise.all( items.map(mapToAccessToken).map(this.deleteApiKeySingle.bind(this)) ).then(onApiKeysDeleted.bind({ instance: this, items: items })); } deleteDevice(id) { return this.deleteDevices([{ Id: id }]); } deleteDeviceSingle(id) { return this.ajax({ type: "POST", url: this.getUrl("Devices/Delete", { Id: id }), }); } deleteDevices(items) { return Promise.all( items.map(mapToId).map(this.deleteDeviceSingle.bind(this)) ).then(onDevicesDeleted.bind({ instance: this, items: items })); } deleteLiveTVTunerDevice(id) { return this.ajax({ type: "POST", url: this.getUrl("LiveTv/TunerHosts/Delete", { Id: id }), }).then(onLiveTVTunerDevicesDeleted.bind({ instance: this })); } deleteLiveTVGuideSource(id) { return this.ajax({ type: "POST", url: this.getUrl("LiveTv/ListingProviders/Delete", { Id: id }), }).then(onLiveTVGuideSourcesDeleted.bind({ instance: this })); } getConfigurationPages(options, signal) { return options?.EnableInUserMenu && !this.isMinServerVersion("4.8.0.20") ? Promise.resolve([]) : this.getJSON( this.getUrl( "web/configurationpages", Object.assign( { PageType: "PluginConfiguration", UserId: this.getCurrentUserId(), }, options ) ), signal ); } getAvailableRecordingOptions() { return this.isMinServerVersion("4.8.0.58") ? this.getJSON(this.getUrl("LiveTV/AvailableRecordingOptions")) : Promise.resolve({ RecordingFolders: [], MovieRecordingFolders: [], SeriesRecordingFolders: [], }); } } (ApiClient.prototype.getUrl = getUrl), (ApiClient.getUrl = getUrl), (ApiClient.prototype.getScaledImageUrl = function (itemId, options) { return this.getImageUrl(itemId, options); }), (ApiClient.isLocalId = isLocalId), (ApiClient.isLocalItem = isLocalItem); export default ApiClient;