3928 lines
121 KiB
JavaScript
3928 lines
121 KiB
JavaScript
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;
|