From db20e9e3ea297c2d4bcb9646b422fb80139186de Mon Sep 17 00:00:00 2001 From: LukePulverenti Date: Thu, 21 Mar 2013 16:20:00 -0400 Subject: [PATCH] update to latest js api client --- MediaBrowser.WebDashboard/ApiClient.js | 2678 +++++++++-------- .../Html/scripts/DashboardPage.js | 20 +- .../Html/scripts/site.js | 10 +- MediaBrowser.WebDashboard/packages.config | 2 +- 4 files changed, 1429 insertions(+), 1281 deletions(-) diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index af26e4614..a9aeedab7 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -1,1393 +1,1533 @@ -/** - * Represents a javascript version of ApiClient. - * This should be kept up to date with all possible api methods and parameters - */ -var ApiClient = { +if (!window.MediaBrowser) { + window.MediaBrowser = {}; +} - serverProtocol: "http", +MediaBrowser.ApiClient = function ($, navigator) { /** - * Gets or sets the host name of the server + * Creates a new api client instance + * @param {String} serverProtocol + * @param {String} serverHostName + * @param {String} serverPortNumber + * @param {String} clientName */ - serverHostName: "localhost", + return function (serverProtocol, serverHostName, serverPortNumber, clientName) { - serverPortNumber: 8096, + var self = this; + var deviceName = "Web Browser"; + var deviceId = SHA1(navigator.userAgent + (navigator.cpuClass || "")); + var currentUserId; - currentUserId: null, + /** + * Gets the server host name. + */ + self.serverHostName = function () { - /** - * Detects the hostname and port of MB server based on the current url - */ - inferServerFromUrl: function () { - - var loc = window.location; - - ApiClient.serverProtocol = loc.protocol; - ApiClient.serverHostName = loc.hostname; - ApiClient.serverPortNumber = loc.port; - }, - - /** - * Creates an api url based on a handler name and query string parameters - * @param {String} name - * @param {Object} params - */ - getUrl: function (name, params) { - - if (!name) { - throw new Error("Url name cannot be empty"); - } - - var url = ApiClient.serverProtocol + "//" + ApiClient.serverHostName + ":" + ApiClient.serverPortNumber + "/mediabrowser/" + name; - - if (params) { - url += "?" + $.param(params); - } - - return url; - }, - - /** - * Returns the name of the current browser - */ - getDeviceName: function () { - - /*if ($.browser.chrome) { - return "Chrome"; - } - if ($.browser.safari) { - return "Safari"; - } - if ($.browser.webkit) { - return "WebKit"; - } - if ($.browser.msie) { - return "Internet Explorer"; - } - if ($.browser.firefox) { - return "Firefox"; - } - if ($.browser.mozilla) { - return "Firefox"; - } - if ($.browser.opera) { - return "Opera"; - }*/ - - return "Web Browser"; - }, - - getDeviceId: function() { - return SHA1(navigator.userAgent + (navigator.cpuClass || "")); - }, - - /** - * Creates a custom api url based on a handler name and query string parameters - * @param {String} name - * @param {Object} params - */ - getCustomUrl: function (name, params) { - - if (!name) { - throw new Error("Url name cannot be empty"); - } - - params = params || {}; - params.format = "json"; - - var url = ApiClient.serverProtocol + "//" + ApiClient.serverHostName + ":" + ApiClient.serverPortNumber + "/mediabrowser/" + name; - - if (params) { - url += "?" + $.param(params); - } - - return url; - }, - - /** - * Gets an item from the server - * Omit itemId to get the root folder. - */ - getItem: function (userId, itemId) { - - if (!userId) { - throw new Error("null userId"); - } - - var url = ApiClient.getUrl("Users/" + userId + "/Items/" + itemId); - - return $.getJSON(url); - }, - - /** - * Gets the root folder from the server - */ - getRootFolder: function (userId) { - - return ApiClient.getItem(userId); - }, - - /** - * Gets the current server status - */ - getSystemInfo: function () { - - var url = ApiClient.getUrl("System/Info"); - - return $.getJSON(url); - }, - - /** - * Gets all cultures known to the server - */ - getCultures: function () { - - var url = ApiClient.getUrl("Localization/cultures"); - - return $.getJSON(url); - }, - - /** - * Gets all countries known to the server - */ - getCountries: function () { - - var url = ApiClient.getUrl("Localization/countries"); - - return $.getJSON(url); - }, - - /** - * Gets plugin security info - */ - getPluginSecurityInfo: function () { - - var url = ApiClient.getUrl("Plugins/SecurityInfo"); - - return $.getJSON(url); - }, - - /** - * Gets the directory contents of a path on the server - */ - getDirectoryContents: function (path, options) { - - if (!path) { - throw new Error("null path"); - } - - options = options || {}; - - options.path = path; - - var url = ApiClient.getUrl("Environment/DirectoryContents", options); - - return $.getJSON(url); - }, - - /** - * Gets a list of physical drives from the server - */ - getDrives: function () { - - var url = ApiClient.getUrl("Environment/Drives"); - - return $.getJSON(url); - }, - - /** - * Gets a list of network devices from the server - */ - getNetworkDevices: function () { - - var url = ApiClient.getUrl("Environment/NetworkDevices"); - - return $.getJSON(url); - }, - - /** - * Cancels a package installation - */ - cancelPackageInstallation: function (installationId) { - - if (!installationId) { - throw new Error("null installationId"); - } - - var url = ApiClient.getUrl("Packages/Installing/" + id); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Installs or updates a new plugin - */ - installPlugin: function (name, updateClass, version) { - - if (!name) { - throw new Error("null name"); - } - - if (!updateClass) { - throw new Error("null updateClass"); - } - - var options = { - updateClass: updateClass + return serverHostName; }; - if (version) { - options.version = version; - } + /** + * Gets the server port number. + */ + self.serverPortNumber = function () { - var url = ApiClient.getUrl("Packages/Installed/" + name, options); - - return $.post(url); - }, - - /** - * Instructs the server to perform a pending kernel reload or app restart. - * If a restart is not currently required, nothing will happen. - */ - performPendingRestart: function () { - - var url = ApiClient.getUrl("System/Restart"); - - return $.post(url); - }, - - /** - * Gets information about an installable package - */ - getPackageInfo: function (name) { - - if (!name) { - throw new Error("null name"); - } - - var url = ApiClient.getUrl("Packages/" + name); - - return $.getJSON(url); - }, - - /** - * Gets the latest available application update (if any) - */ - getAvailableApplicationUpdate: function () { - - var url = ApiClient.getUrl("Packages/Updates", { PackageType: "System" }); - - return $.getJSON(url); - }, - - /** - * Gets the latest available plugin updates (if any) - */ - getAvailablePluginUpdates: function () { - - var url = ApiClient.getUrl("Packages/Updates", { PackageType: "UserInstalled" }); - - return $.getJSON(url); - }, - - /** - * Gets the virtual folder for a view. Specify a userId to get a user view, or omit for the default view. - */ - getVirtualFolders: function (userId) { - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url = ApiClient.getUrl(url); - - return $.getJSON(url); - }, - - /** - * Gets all the paths of the locations in the physical root. - */ - getPhysicalPaths: function () { - - var url = ApiClient.getUrl("Library/PhysicalPaths"); - - return $.getJSON(url); - }, - - /** - * Gets the current server configuration - */ - getServerConfiguration: function () { - - var url = ApiClient.getUrl("System/Configuration"); - - return $.getJSON(url); - }, - - /** - * Gets the server's scheduled tasks - */ - getScheduledTasks: function () { - - var url = ApiClient.getUrl("ScheduledTasks"); - - return $.getJSON(url); - }, - - /** - * Starts a scheduled task - */ - startScheduledTask: function (id) { - - if (!id) { - throw new Error("null id"); - } - - var url = ApiClient.getUrl("ScheduledTasks/Running/" + id); - - return $.post(url); - }, - - /** - * Gets a scheduled task - */ - getScheduledTask: function (id) { - - if (!id) { - throw new Error("null id"); - } - - var url = ApiClient.getUrl("ScheduledTasks/" + id); - - return $.getJSON(url); - }, - - /** - * Stops a scheduled task - */ - stopScheduledTask: function (id) { - - if (!id) { - throw new Error("null id"); - } - - var url = ApiClient.getUrl("ScheduledTasks/Running/" + id); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Gets the configuration of a plugin - * @param {String} Id - */ - getPluginConfiguration: function (id) { - - if (!id) { - throw new Error("null Id"); - } - - var url = ApiClient.getUrl("Plugins/" + id + "/Configuration"); - - return $.getJSON(url); - }, - - /** - * Gets a list of plugins that are available to be installed - */ - getAvailablePlugins: function () { - - var url = ApiClient.getUrl("Packages", { PackageType: "UserInstalled" }); - - return $.getJSON(url); - }, - - /** - * Uninstalls a plugin - * @param {String} Id - */ - uninstallPlugin: function (id) { - - if (!id) { - throw new Error("null Id"); - } - - var url = ApiClient.getUrl("Plugins/" + id); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Removes a virtual folder from either the default view or a user view - * @param {String} name - */ - removeVirtualFolder: function (name, userId) { - - if (!name) { - throw new Error("null name"); - } - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url += "/" + name; - url = ApiClient.getUrl(url); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Adds a virtual folder to either the default view or a user view - * @param {String} name - */ - addVirtualFolder: function (name, userId) { - - if (!name) { - throw new Error("null name"); - } - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url += "/" + name; - url = ApiClient.getUrl(url); - - return $.post(url); - }, - - /** - * Renames a virtual folder, within either the default view or a user view - * @param {String} name - */ - renameVirtualFolder: function (name, newName, userId) { - - if (!name) { - throw new Error("null name"); - } - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url += "/" + name + "/Name"; - - url = ApiClient.getUrl(url, { newName: newName }); - - return $.post(url); - }, - - /** - * Adds an additional mediaPath to an existing virtual folder, within either the default view or a user view - * @param {String} name - */ - addMediaPath: function (virtualFolderName, mediaPath, userId) { - - if (!virtualFolderName) { - throw new Error("null virtualFolderName"); - } - - if (!mediaPath) { - throw new Error("null mediaPath"); - } - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url += "/" + virtualFolderName + "/Paths"; - - url = ApiClient.getUrl(url, { path: mediaPath }); - - return $.post(url); - }, - - /** - * Removes a media path from a virtual folder, within either the default view or a user view - * @param {String} name - */ - removeMediaPath: function (virtualFolderName, mediaPath, userId) { - - if (!virtualFolderName) { - throw new Error("null virtualFolderName"); - } - - if (!mediaPath) { - throw new Error("null mediaPath"); - } - - var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - - url += "/" + virtualFolderName + "/Paths"; - - url = ApiClient.getUrl(url, { path: mediaPath }); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Deletes a user - * @param {String} id - */ - deleteUser: function (id) { - - if (!id) { - throw new Error("null id"); - } - - var url = ApiClient.getUrl("Users/" + id); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Deletes a user image - * @param {String} userId - * @param {String} imageType The type of image to delete, based on the server-side ImageType enum. - */ - deleteUserImage: function (userId, imageType) { - - if (!userId) { - throw new Error("null userId"); - } - - if (!imageType) { - throw new Error("null imageType"); - } - - var url = ApiClient.getUrl("Users/" + userId + "/Images/" + imageType); - - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - }, - - /** - * Uploads a user image - * @param {String} userId - * @param {String} imageType The type of image to delete, based on the server-side ImageType enum. - * @param {Object} file The file from the input element - */ - uploadUserImage: function (userId, imageType, file) { - - if (!userId) { - throw new Error("null userId"); - } - - if (!imageType) { - throw new Error("null imageType"); - } - - if (!file || !file.type.match('image.*')) { - throw new Error("File must be an image."); - } - - var deferred = $.Deferred(); - - var reader = new FileReader(); - - reader.onerror = function () { - deferred.reject(); + return serverPortNumber; }; - reader.onabort = function () { - deferred.reject(); + /** + * Gets or sets the current user id. + */ + self.currentUserId = function (val) { + + if (val !== undefined) { + currentUserId = val; + } else { + return currentUserId; + } }; - // Closure to capture the file information. - reader.onload = function (e) { + self.ajax = function (request) { - var data = window.btoa(e.target.result); + if (!request) { + throw new Error("Request cannot be null"); + } - var url = ApiClient.getUrl("Users/" + userId + "/Images/" + imageType); + var auth = 'MediaBrowser Client="' + clientName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '"'; - $.ajax({ - type: "POST", + if (currentUserId) { + auth += ', UserId="' + currentUserId + '"'; + } + + request.headers = { + Authorization: auth + }; + + return $.ajax(request); + }; + + /** + * Creates an api url based on a handler name and query string parameters + * @param {String} name + * @param {Object} params + */ + self.getUrl = function (name, params) { + + if (!name) { + throw new Error("Url name cannot be empty"); + } + + var url = serverProtocol + "//" + serverHostName + ":" + serverPortNumber + "/mediabrowser/" + name; + + if (params) { + url += "?" + $.param(params); + } + + return url; + }; + + /** + * Gets an item from the server + * Omit itemId to get the root folder. + */ + self.getItem = function (userId, itemId) { + + if (!userId) { + throw new Error("null userId"); + } + + var url = self.getUrl("Users/" + userId + "/Items/" + itemId); + + return self.ajax({ + type: "GET", url: url, - data: data, - contentType: "image/" + file.name.substring(file.name.lastIndexOf('.') + 1) - - }).done(function (result) { - - deferred.resolveWith(null, [result]); - - }).fail(function () { - deferred.reject(); + dataType: "json" }); }; - // Read in the image file as a data URL. - reader.readAsBinaryString(file); + /** + * Gets the root folder from the server + */ + self.getRootFolder = function (userId) { - return deferred.promise(); - }, - - /** - * Gets the list of installed plugins on the server - */ - getInstalledPlugins: function () { - - var url = ApiClient.getUrl("Plugins"); - - return $.getJSON(url); - }, - - /** - * Gets a user by id - * @param {String} id - */ - getUser: function (id) { - - if (!id) { - throw new Error("Must supply a userId"); - } - - var url = ApiClient.getUrl("Users/" + id); - - return $.getJSON(url); - }, - - /** - * Gets a studio - */ - getStudio: function (name) { - - if (!name) { - throw new Error("null name"); - } - - var url = ApiClient.getUrl("Studios/" + name); - - return $.getJSON(url); - }, - - /** - * Gets a genre - */ - getGenre: function (name) { - - if (!name) { - throw new Error("null name"); - } - - var url = ApiClient.getUrl("Genres/" + name); - - return $.getJSON(url); - }, - - /** - * Gets a year - */ - getYear: function (year) { - - if (!year) { - throw new Error("null year"); - } - - var url = ApiClient.getUrl("Years/" + year); - - return $.getJSON(url); - }, - - /** - * Gets a Person - */ - getPerson: function (name) { - - if (!name) { - throw new Error("null name"); - } - - var url = ApiClient.getUrl("Persons/" + name); - - return $.getJSON(url); - }, - - /** - * Gets weather info - * @param {String} location - us zip code / city, state, country / city, country - * Omit location to get weather info using stored server configuration value - */ - getWeatherInfo: function (location) { - - var url = ApiClient.getUrl("weather", { - location: location - }); - - return $.getJSON(url); - }, - - /** - * Gets all users from the server - */ - getAllUsers: function () { - - var url = ApiClient.getUrl("users"); - - return $.getJSON(url); - }, - - /** - * Gets all available parental ratings from the server - */ - getParentalRatings: function () { - - var url = ApiClient.getUrl("Localization/ParentalRatings"); - - return $.getJSON(url); - }, - - /** - * Gets a list of all available conrete BaseItem types from the server - */ - getItemTypes: function (options) { - - var url = ApiClient.getUrl("Library/ItemTypes", options); - - return $.getJSON(url); - }, - - /** - * Constructs a url for a user image - * @param {String} userId - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getUserImageUrl: function (userId, options) { - - if (!userId) { - throw new Error("null userId"); - } - - options = options || { + return self.getItem(userId); }; - var url = "Users/" + userId + "/Images/" + options.type; + /** + * Gets the current server status + */ + self.getSystemInfo = function () { - if (options.index != null) { - url += "/" + options.index; - } + var url = self.getUrl("System/Info"); - // Don't put these on the query string - delete options.type; - delete options.index; - - return ApiClient.getUrl(url, options); - }, - - /** - * Constructs a url for a person image - * @param {String} name - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getPersonImageUrl: function (name, options) { - - if (!name) { - throw new Error("null name"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - var url = "Persons/" + name + "/Images/" + options.type; + /** + * Gets all cultures known to the server + */ + self.getCultures = function () { - if (options.index != null) { - url += "/" + options.index; - } + var url = self.getUrl("Localization/cultures"); - // Don't put these on the query string - delete options.type; - delete options.index; - - return ApiClient.getUrl(url, options); - }, - - /** - * Constructs a url for a year image - * @param {String} year - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getYearImageUrl: function (year, options) { - - if (!year) { - throw new Error("null year"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - var url = "Years/" + year + "/Images/" + options.type; + /** + * Gets all countries known to the server + */ + self.getCountries = function () { - if (options.index != null) { - url += "/" + options.index; - } + var url = self.getUrl("Localization/countries"); - // Don't put these on the query string - delete options.type; - delete options.index; - - return ApiClient.getUrl(url, options); - }, - - /** - * Constructs a url for a genre image - * @param {String} name - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getGenreImageUrl: function (name, options) { - - if (!name) { - throw new Error("null name"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - var url = "Genres/" + name + "/Images/" + options.type; + /** + * Gets plugin security info + */ + self.getPluginSecurityInfo = function () { - if (options.index != null) { - url += "/" + options.index; - } + var url = self.getUrl("Plugins/SecurityInfo"); - // Don't put these on the query string - delete options.type; - delete options.index; - - return ApiClient.getUrl(url, options); - }, - - /** - * Constructs a url for a genre image - * @param {String} name - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getStudioImageUrl: function (name, options) { - - if (!name) { - throw new Error("null name"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - var url = "Studios/" + name + "/Images/" + options.type; + /** + * Gets the directory contents of a path on the server + */ + self.getDirectoryContents = function (path, options) { - if (options.index != null) { - url += "/" + options.index; - } + if (!path) { + throw new Error("null path"); + } - // Don't put these on the query string - delete options.type; - delete options.index; + options = options || {}; - return ApiClient.getUrl(url, options); - }, + options.path = path; - /** - * Constructs a url for an item image - * @param {String} itemId - * @param {Object} options - * Options supports the following properties: - * type - Primary, logo, backdrop, etc. See the server-side enum ImageType - * index - When downloading a backdrop, use this to specify which one (omitting is equivalent to zero) - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getImageUrl: function (itemId, options) { + var url = self.getUrl("Environment/DirectoryContents", options); - if (!itemId) { - throw new Error("itemId cannot be empty"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - var url = "Items/" + itemId + "/Images/" + options.type; + /** + * Gets a list of physical drives from the server + */ + self.getDrives = function () { - if (options.index != null) { - url += "/" + options.index; - } + var url = self.getUrl("Environment/Drives"); - // Don't put these on the query string - delete options.type; - delete options.index; - - return ApiClient.getUrl(url, options); - }, - - /** - * Constructs a url for an item logo image - * If the item doesn't have a logo, it will inherit a logo from a parent - * @param {Object} item A BaseItem - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getLogoImageUrl: function (item, options) { - - if (!item) { - throw new Error("null item"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - options.imageType = "logo"; + /** + * Gets a list of network devices from the server + */ + self.getNetworkDevices = function () { - var logoItemId = item.HasLogo ? item.Id : item.ParentLogoItemId; + var url = self.getUrl("Environment/NetworkDevices"); - return logoItemId ? ApiClient.getImageUrl(logoItemId, options) : null; - }, - - /** - * Constructs an array of backdrop image url's for an item - * If the item doesn't have any backdrops, it will inherit them from a parent - * @param {Object} item A BaseItem - * @param {Object} options - * Options supports the following properties: - * width - download the image at a fixed width - * height - download the image at a fixed height - * maxWidth - download the image at a maxWidth - * maxHeight - download the image at a maxHeight - * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. - * For best results do not specify both width and height together, as aspect ratio might be altered. - */ - getBackdropImageUrl: function (item, options) { - - if (!item) { - throw new Error("null item"); - } - - options = options || { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); }; - options.imageType = "backdrop"; + /** + * Cancels a package installation + */ + self.cancelPackageInstallation = function (installationId) { - var backdropItemId; - var backdropCount; + if (!installationId) { + throw new Error("null installationId"); + } - if (!item.BackdropCount) { - backdropItemId = item.ParentBackdropItemId; - backdropCount = item.ParentBackdropCount || 0; - } else { - backdropItemId = item.Id; - backdropCount = item.BackdropCount; - } + var url = self.getUrl("Packages/Installing/" + id); - if (!backdropItemId) { - return []; - } - - var files = []; - - for (var i = 0; i < backdropCount; i++) { - - options.imageIndex = i; - - files[i] = ApiClient.getImageUrl(backdropItemId, options); - } - - return files; - }, - - /** - * Authenticates a user - * @param {String} userId - * @param {String} password - */ - authenticateUser: function (userId, password) { - - if (!userId) { - throw new Error("null userId"); - } - - var url = ApiClient.getUrl("Users/" + userId + "/authenticate"); - - var postData = { - password: SHA1(password || "") + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); }; - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(postData), - dataType: "json", - contentType: "application/json" - }); - }, + /** + * Installs or updates a new plugin + */ + self.installPlugin = function (name, updateClass, version) { - /** - * Updates a user's password - * @param {String} userId - * @param {String} currentPassword - * @param {String} newPassword - */ - updateUserPassword: function (userId, currentPassword, newPassword) { + if (!name) { + throw new Error("null name"); + } - if (!userId) { - throw new Error("null userId"); - } + if (!updateClass) { + throw new Error("null updateClass"); + } - var url = ApiClient.getUrl("Users/" + userId + "/Password"); + var options = { + updateClass: updateClass + }; - var postData = { + if (version) { + options.version = version; + } + + var url = self.getUrl("Packages/Installed/" + name, options); + + return self.ajax({ + type: "POST", + url: url + }); }; - postData.currentPassword = SHA1(currentPassword); - if (newPassword) { - postData.newPassword = newPassword; - } - return $.post(url, postData); - }, + /** + * Instructs the server to perform a pending kernel reload or app restart. + * If a restart is not currently required, nothing will happen. + */ + self.performPendingRestart = function () { - /** - * Resets a user's password - * @param {String} userId - */ - resetUserPassword: function (userId) { + var url = self.getUrl("System/Restart"); - if (!userId) { - throw new Error("null userId"); - } - - var url = ApiClient.getUrl("Users/" + userId + "/Password"); - - var postData = { + return self.ajax({ + type: "POST", + url: url + }); }; - postData.resetPassword = true; - return $.post(url, postData); - }, + /** + * Gets information about an installable package + */ + self.getPackageInfo = function (name) { - /** - * Updates the server's configuration - * @param {Object} configuration - */ - updateServerConfiguration: function (configuration) { + if (!name) { + throw new Error("null name"); + } - if (!configuration) { - throw new Error("null configuration"); - } + var url = self.getUrl("Packages/" + name); - var url = ApiClient.getUrl("System/Configuration"); + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(configuration), - dataType: "json", - contentType: "application/json" - }); - }, + /** + * Gets the latest available application update (if any) + */ + self.getAvailableApplicationUpdate = function () { - /** - * Updates plugin security info - */ - updatePluginSecurityInfo: function (info) { + var url = self.getUrl("Packages/Updates", { PackageType: "System" }); - var url = ApiClient.getUrl("Plugins/SecurityInfo"); + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(info), - dataType: "json", - contentType: "application/json" - }); - }, + /** + * Gets the latest available plugin updates (if any) + */ + self.getAvailablePluginUpdates = function () { - /** - * Creates a user - * @param {Object} user - */ - createUser: function (user) { + var url = self.getUrl("Packages/Updates", { PackageType: "UserInstalled" }); - if (!user) { - throw new Error("null user"); - } + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - var url = ApiClient.getUrl("Users"); + /** + * Gets the virtual folder for a view. Specify a userId to get a user view, or omit for the default view. + */ + self.getVirtualFolders = function (userId) { - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(user), - dataType: "json", - contentType: "application/json" - }); - }, + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - /** - * Updates a user - * @param {Object} user - */ - updateUser: function (user) { + url = self.getUrl(url); - if (!user) { - throw new Error("null user"); - } + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - var url = ApiClient.getUrl("Users/" + user.Id); + /** + * Gets all the paths of the locations in the physical root. + */ + self.getPhysicalPaths = function () { - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(user), - dataType: "json", - contentType: "application/json" - }); - }, + var url = self.getUrl("Library/PhysicalPaths"); - /** - * Updates the Triggers for a ScheduledTask - * @param {String} id - * @param {Object} triggers - */ - updateScheduledTaskTriggers: function (id, triggers) { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - if (!id) { - throw new Error("null id"); - } + /** + * Gets the current server configuration + */ + self.getServerConfiguration = function () { - if (!triggers) { - throw new Error("null triggers"); - } + var url = self.getUrl("System/Configuration"); - var url = ApiClient.getUrl("ScheduledTasks/" + id + "/Triggers"); + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(triggers), - dataType: "json", - contentType: "application/json" - }); - }, + /** + * Gets the server's scheduled tasks + */ + self.getScheduledTasks = function () { - /** - * Updates a plugin's configuration - * @param {String} Id - * @param {Object} configuration - */ - updatePluginConfiguration: function (id, configuration) { + var url = self.getUrl("ScheduledTasks"); - if (!id) { - throw new Error("null Id"); - } + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - if (!configuration) { - throw new Error("null configuration"); - } + /** + * Starts a scheduled task + */ + self.startScheduledTask = function (id) { - var url = ApiClient.getUrl("Plugins/" + id + "/Configuration"); + if (!id) { + throw new Error("null id"); + } - return $.ajax({ - type: "POST", - url: url, - data: JSON.stringify(configuration), - dataType: "json", - contentType: "application/json" - }); - }, + var url = self.getUrl("ScheduledTasks/Running/" + id); - /** - * Gets items based on a query, typicall for children of a folder - * @param {String} userId - * @param {Object} options - * Options accepts the following properties: - * itemId - Localize the search to a specific folder (root if omitted) - * startIndex - Use for paging - * limit - Use to limit results to a certain number of items - * filter - Specify one or more ItemFilters, comma delimeted (see server-side enum) - * sortBy - Specify an ItemSortBy (comma-delimeted list see server-side enum) - * sortOrder - ascending/descending - * fields - additional fields to include aside from basic info. This is a comma delimited list. See server-side enum ItemFields. - * index - the name of the dynamic, localized index function - * dynamicSortBy - the name of the dynamic localized sort function - * recursive - Whether or not the query should be recursive - * searchTerm - search term to use as a filter - */ - getItems: function (userId, options) { + return self.ajax({ + type: "POST", + url: url + }); + }; - if (!userId) { - throw new Error("null userId"); - } + /** + * Gets a scheduled task + */ + self.getScheduledTask = function (id) { - return $.getJSON(ApiClient.getUrl("Users/" + userId + "/Items", options)); - }, + if (!id) { + throw new Error("null id"); + } - /** - * Marks an item as played or unplayed - * This should not be used to update playstate following playback. - * There are separate playstate check-in methods for that. This should be used for a - * separate option to reset playstate. - * @param {String} userId - * @param {String} itemId - * @param {Boolean} wasPlayed - */ - updatePlayedStatus: function (userId, itemId, wasPlayed) { + var url = self.getUrl("ScheduledTasks/" + id); - if (!userId) { - throw new Error("null userId"); - } + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - if (!itemId) { - throw new Error("null itemId"); - } + /** + * Stops a scheduled task + */ + self.stopScheduledTask = function (id) { - var url = "Users/" + userId + "/PlayedItems/" + itemId; + if (!id) { + throw new Error("null id"); + } - var method = wasPlayed ? "POST" : "DELETE"; + var url = self.getUrl("ScheduledTasks/Running/" + id); - return $.ajax({ - type: method, - url: url, - dataType: "json" - }); - }, + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; - /** - * Updates a user's favorite status for an item and returns the updated UserItemData object. - * @param {String} userId - * @param {String} itemId - * @param {Boolean} isFavorite - */ - updateFavoriteStatus: function (userId, itemId, isFavorite) { + /** + * Gets the configuration of a plugin + * @param {String} Id + */ + self.getPluginConfiguration = function (id) { - if (!userId) { - throw new Error("null userId"); - } + if (!id) { + throw new Error("null Id"); + } - if (!itemId) { - throw new Error("null itemId"); - } + var url = self.getUrl("Plugins/" + id + "/Configuration"); - var url = "Users/" + userId + "/FavoriteItems/" + itemId; + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - var method = isFavorite ? "POST" : "DELETE"; + /** + * Gets a list of plugins that are available to be installed + */ + self.getAvailablePlugins = function () { - return $.ajax({ - type: method, - url: url, - dataType: "json" - }); - }, + var url = self.getUrl("Packages", { PackageType: "UserInstalled" }); - /** - * Updates a user's personal rating for an item - * @param {String} userId - * @param {String} itemId - * @param {Boolean} likes - */ - updateUserItemRating: function (userId, itemId, likes) { + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; - if (!userId) { - throw new Error("null userId"); - } + /** + * Uninstalls a plugin + * @param {String} Id + */ + self.uninstallPlugin = function (id) { - if (!itemId) { - throw new Error("null itemId"); - } + if (!id) { + throw new Error("null Id"); + } - var url = ApiClient.getUrl("Users/" + userId + "/Items/" + itemId + "/Rating", { - likes: likes - }); + var url = self.getUrl("Plugins/" + id); - return $.post(url); - }, + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; - /** - * Clears a user's personal rating for an item - * @param {String} userId - * @param {String} itemId - */ - clearUserItemRating: function (userId, itemId) { + /** + * Removes a virtual folder from either the default view or a user view + * @param {String} name + */ + self.removeVirtualFolder = function (name, userId) { - if (!userId) { - throw new Error("null userId"); - } + if (!name) { + throw new Error("null name"); + } - if (!itemId) { - throw new Error("null itemId"); - } + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - var url = ApiClient.getUrl("Users/" + userId + "/Items/" + itemId + "/Rating"); + url += "/" + name; + url = self.getUrl(url); - return $.ajax({ - type: "DELETE", - url: url, - dataType: "json" - }); - } -}; + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; -// Do this initially. The consumer can always override later -ApiClient.inferServerFromUrl(); + /** + * Adds a virtual folder to either the default view or a user view + * @param {String} name + */ + self.addVirtualFolder = function (name, userId) { -$(document).ajaxSend(function (event, jqXHR) { + if (!name) { + throw new Error("null name"); + } - if (ApiClient.currentUserId) { + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; - var auth = 'MediaBrowser UserId="' + ApiClient.currentUserId + '", Client="Dashboard", Device="' + ApiClient.getDeviceName() + '", DeviceId="' + ApiClient.getDeviceId() + '"'; - jqXHR.setRequestHeader("Authorization", auth); - } -}); \ No newline at end of file + url += "/" + name; + url = self.getUrl(url); + + return self.ajax({ + type: "POST", + url: url + }); + }; + + /** + * Renames a virtual folder, within either the default view or a user view + * @param {String} name + */ + self.renameVirtualFolder = function (name, newName, userId) { + + if (!name) { + throw new Error("null name"); + } + + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; + + url += "/" + name + "/Name"; + + url = self.getUrl(url, { newName: newName }); + + return self.ajax({ + type: "POST", + url: url + }); + }; + + /** + * Adds an additional mediaPath to an existing virtual folder, within either the default view or a user view + * @param {String} name + */ + self.addMediaPath = function (virtualFolderName, mediaPath, userId) { + + if (!virtualFolderName) { + throw new Error("null virtualFolderName"); + } + + if (!mediaPath) { + throw new Error("null mediaPath"); + } + + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; + + url += "/" + virtualFolderName + "/Paths"; + + url = self.getUrl(url, { path: mediaPath }); + + return self.ajax({ + type: "POST", + url: url + }); + }; + + /** + * Removes a media path from a virtual folder, within either the default view or a user view + * @param {String} name + */ + self.removeMediaPath = function (virtualFolderName, mediaPath, userId) { + + if (!virtualFolderName) { + throw new Error("null virtualFolderName"); + } + + if (!mediaPath) { + throw new Error("null mediaPath"); + } + + var url = userId ? "Users/" + userId + "/VirtualFolders" : "Library/VirtualFolders"; + + url += "/" + virtualFolderName + "/Paths"; + + url = self.getUrl(url, { path: mediaPath }); + + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; + + /** + * Deletes a user + * @param {String} id + */ + self.deleteUser = function (id) { + + if (!id) { + throw new Error("null id"); + } + + var url = self.getUrl("Users/" + id); + + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; + + /** + * Deletes a user image + * @param {String} userId + * @param {String} imageType The type of image to delete, based on the server-side ImageType enum. + */ + self.deleteUserImage = function (userId, imageType) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!imageType) { + throw new Error("null imageType"); + } + + var url = self.getUrl("Users/" + userId + "/Images/" + imageType); + + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; + + /** + * Uploads a user image + * @param {String} userId + * @param {String} imageType The type of image to delete, based on the server-side ImageType enum. + * @param {Object} file The file from the input element + */ + self.uploadUserImage = function (userId, imageType, file) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!imageType) { + throw new Error("null imageType"); + } + + if (!file || !file.type.match('image.*')) { + throw new Error("File must be an image."); + } + + var deferred = $.Deferred(); + + var reader = new FileReader(); + + reader.onerror = function () { + deferred.reject(); + }; + + reader.onabort = function () { + deferred.reject(); + }; + + // Closure to capture the file information. + reader.onload = function (e) { + + var data = window.btoa(e.target.result); + + var url = self.getUrl("Users/" + userId + "/Images/" + imageType); + + self.ajax({ + type: "POST", + url: url, + data: data, + contentType: "image/" + file.name.substring(file.name.lastIndexOf('.') + 1) + }).done(function (result) { + + deferred.resolveWith(null, [result]); + + }).fail(function () { + deferred.reject(); + }); + }; + + // Read in the image file as a data URL. + reader.readAsBinaryString(file); + + return deferred.promise(); + }; + + /** + * Gets the list of installed plugins on the server + */ + self.getInstalledPlugins = function () { + + var url = self.getUrl("Plugins"); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a user by id + * @param {String} id + */ + self.getUser = function (id) { + + if (!id) { + throw new Error("Must supply a userId"); + } + + var url = self.getUrl("Users/" + id); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a studio + */ + self.getStudio = function (name) { + + if (!name) { + throw new Error("null name"); + } + + var url = self.getUrl("Studios/" + name); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a genre + */ + self.getGenre = function (name) { + + if (!name) { + throw new Error("null name"); + } + + var url = self.getUrl("Genres/" + name); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a year + */ + self.getYear = function (year) { + + if (!year) { + throw new Error("null year"); + } + + var url = self.getUrl("Years/" + year); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a Person + */ + self.getPerson = function (name) { + + if (!name) { + throw new Error("null name"); + } + + var url = self.getUrl("Persons/" + name); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets weather info + * @param {String} location - us zip code / city, state, country / city, country + * Omit location to get weather info using stored server configuration value + */ + self.getWeatherInfo = function (location) { + + var url = self.getUrl("weather", { + location: location + }); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets all users from the server + */ + self.getAllUsers = function () { + + var url = self.getUrl("users"); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets all available parental ratings from the server + */ + self.getParentalRatings = function () { + + var url = self.getUrl("Localization/ParentalRatings"); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Gets a list of all available conrete BaseItem types from the server + */ + self.getItemTypes = function (options) { + + var url = self.getUrl("Library/ItemTypes", options); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Constructs a url for a user image + * @param {String} userId + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getUserImageUrl = function (userId, options) { + + if (!userId) { + throw new Error("null userId"); + } + + options = options || { + + }; + + var url = "Users/" + userId + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for a person image + * @param {String} name + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getPersonImageUrl = function (name, options) { + + if (!name) { + throw new Error("null name"); + } + + options = options || { + + }; + + var url = "Persons/" + name + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for a year image + * @param {String} year + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getYearImageUrl = function (year, options) { + + if (!year) { + throw new Error("null year"); + } + + options = options || { + + }; + + var url = "Years/" + year + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for a genre image + * @param {String} name + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getGenreImageUrl = function (name, options) { + + if (!name) { + throw new Error("null name"); + } + + options = options || { + + }; + + var url = "Genres/" + name + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for a genre image + * @param {String} name + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getStudioImageUrl = function (name, options) { + + if (!name) { + throw new Error("null name"); + } + + options = options || { + + }; + + var url = "Studios/" + name + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for an item image + * @param {String} itemId + * @param {Object} options + * Options supports the following properties: + * type - Primary, logo, backdrop, etc. See the server-side enum ImageType + * index - When downloading a backdrop, use this to specify which one (omitting is equivalent to zero) + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getImageUrl = function (itemId, options) { + + if (!itemId) { + throw new Error("itemId cannot be empty"); + } + + options = options || { + + }; + + var url = "Items/" + itemId + "/Images/" + options.type; + + if (options.index != null) { + url += "/" + options.index; + } + + // Don't put these on the query string + delete options.type; + delete options.index; + + return self.getUrl(url, options); + }; + + /** + * Constructs a url for an item logo image + * If the item doesn't have a logo, it will inherit a logo from a parent + * @param {Object} item A BaseItem + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getLogoImageUrl = function (item, options) { + + if (!item) { + throw new Error("null item"); + } + + options = options || { + + }; + + options.imageType = "logo"; + + var logoItemId = item.HasLogo ? item.Id : item.ParentLogoItemId; + + return logoItemId ? self.getImageUrl(logoItemId, options) : null; + }; + + /** + * Constructs an array of backdrop image url's for an item + * If the item doesn't have any backdrops, it will inherit them from a parent + * @param {Object} item A BaseItem + * @param {Object} options + * Options supports the following properties: + * width - download the image at a fixed width + * height - download the image at a fixed height + * maxWidth - download the image at a maxWidth + * maxHeight - download the image at a maxHeight + * quality - A scale of 0-100. This should almost always be omitted as the default will suffice. + * For best results do not specify both width and height together, as aspect ratio might be altered. + */ + self.getBackdropImageUrl = function (item, options) { + + if (!item) { + throw new Error("null item"); + } + + options = options || { + + }; + + options.imageType = "backdrop"; + + var backdropItemId; + var backdropCount; + + if (!item.BackdropCount) { + backdropItemId = item.ParentBackdropItemId; + backdropCount = item.ParentBackdropCount || 0; + } else { + backdropItemId = item.Id; + backdropCount = item.BackdropCount; + } + + if (!backdropItemId) { + return []; + } + + var files = []; + + for (var i = 0; i < backdropCount; i++) { + + options.imageIndex = i; + + files[i] = self.getImageUrl(backdropItemId, options); + } + + return files; + }; + + /** + * Authenticates a user + * @param {String} userId + * @param {String} password + */ + self.authenticateUser = function (userId, password) { + + if (!userId) { + throw new Error("null userId"); + } + + var url = self.getUrl("Users/" + userId + "/authenticate"); + + var postData = { + password: SHA1(password || "") + }; + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(postData), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Updates a user's password + * @param {String} userId + * @param {String} currentPassword + * @param {String} newPassword + */ + self.updateUserPassword = function (userId, currentPassword, newPassword) { + + if (!userId) { + throw new Error("null userId"); + } + + var url = self.getUrl("Users/" + userId + "/Password"); + + var postData = { + + }; + + postData.currentPassword = SHA1(currentPassword); + + if (newPassword) { + postData.newPassword = newPassword; + } + + return self.ajax({ + type: "POST", + url: url, + data: postData + }); + }; + + /** + * Resets a user's password + * @param {String} userId + */ + self.resetUserPassword = function (userId) { + + if (!userId) { + throw new Error("null userId"); + } + + var url = self.getUrl("Users/" + userId + "/Password"); + + var postData = { + + }; + + postData.resetPassword = true; + + return self.ajax({ + type: "POST", + url: url, + data: postData + }); + }; + + /** + * Updates the server's configuration + * @param {Object} configuration + */ + self.updateServerConfiguration = function (configuration) { + + if (!configuration) { + throw new Error("null configuration"); + } + + var url = self.getUrl("System/Configuration"); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(configuration), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Updates plugin security info + */ + self.updatePluginSecurityInfo = function (info) { + + var url = self.getUrl("Plugins/SecurityInfo"); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(info), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Creates a user + * @param {Object} user + */ + self.createUser = function (user) { + + if (!user) { + throw new Error("null user"); + } + + var url = self.getUrl("Users"); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(user), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Updates a user + * @param {Object} user + */ + self.updateUser = function (user) { + + if (!user) { + throw new Error("null user"); + } + + var url = self.getUrl("Users/" + user.Id); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(user), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Updates the Triggers for a ScheduledTask + * @param {String} id + * @param {Object} triggers + */ + self.updateScheduledTaskTriggers = function (id, triggers) { + + if (!id) { + throw new Error("null id"); + } + + if (!triggers) { + throw new Error("null triggers"); + } + + var url = self.getUrl("ScheduledTasks/" + id + "/Triggers"); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(triggers), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Updates a plugin's configuration + * @param {String} Id + * @param {Object} configuration + */ + self.updatePluginConfiguration = function (id, configuration) { + + if (!id) { + throw new Error("null Id"); + } + + if (!configuration) { + throw new Error("null configuration"); + } + + var url = self.getUrl("Plugins/" + id + "/Configuration"); + + return self.ajax({ + type: "POST", + url: url, + data: JSON.stringify(configuration), + dataType: "json", + contentType: "application/json" + }); + }; + + /** + * Gets items based on a query, typicall for children of a folder + * @param {String} userId + * @param {Object} options + * Options accepts the following properties: + * itemId - Localize the search to a specific folder (root if omitted) + * startIndex - Use for paging + * limit - Use to limit results to a certain number of items + * filter - Specify one or more ItemFilters, comma delimeted (see server-side enum) + * sortBy - Specify an ItemSortBy (comma-delimeted list see server-side enum) + * sortOrder - ascending/descending + * fields - additional fields to include aside from basic info. This is a comma delimited list. See server-side enum ItemFields. + * index - the name of the dynamic, localized index function + * dynamicSortBy - the name of the dynamic localized sort function + * recursive - Whether or not the query should be recursive + * searchTerm - search term to use as a filter + */ + self.getItems = function (userId, options) { + + if (!userId) { + throw new Error("null userId"); + } + + var url = self.getUrl("Users/" + userId + "/Items", options); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + + /** + * Marks an item as played or unplayed + * This should not be used to update playstate following playback. + * There are separate playstate check-in methods for that. This should be used for a + * separate option to reset playstate. + * @param {String} userId + * @param {String} itemId + * @param {Boolean} wasPlayed + */ + self.updatePlayedStatus = function (userId, itemId, wasPlayed) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!itemId) { + throw new Error("null itemId"); + } + + var url = "Users/" + userId + "/PlayedItems/" + itemId; + + var method = wasPlayed ? "POST" : "DELETE"; + + return self.ajax({ + type: method, + url: url, + dataType: "json" + }); + }; + + /** + * Updates a user's favorite status for an item and returns the updated UserItemData object. + * @param {String} userId + * @param {String} itemId + * @param {Boolean} isFavorite + */ + self.updateFavoriteStatus = function (userId, itemId, isFavorite) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!itemId) { + throw new Error("null itemId"); + } + + var url = "Users/" + userId + "/FavoriteItems/" + itemId; + + var method = isFavorite ? "POST" : "DELETE"; + + return self.ajax({ + type: method, + url: url, + dataType: "json" + }); + }; + + /** + * Updates a user's personal rating for an item + * @param {String} userId + * @param {String} itemId + * @param {Boolean} likes + */ + self.updateUserItemRating = function (userId, itemId, likes) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!itemId) { + throw new Error("null itemId"); + } + + var url = self.getUrl("Users/" + userId + "/Items/" + itemId + "/Rating", { + likes: likes + }); + + return self.ajax({ + type: "POST", + url: url + }); + }; + + /** + * Clears a user's personal rating for an item + * @param {String} userId + * @param {String} itemId + */ + self.clearUserItemRating = function (userId, itemId) { + + if (!userId) { + throw new Error("null userId"); + } + + if (!itemId) { + throw new Error("null itemId"); + } + + var url = self.getUrl("Users/" + userId + "/Items/" + itemId + "/Rating"); + + return self.ajax({ + type: "DELETE", + url: url, + dataType: "json" + }); + }; + }; + +}(jQuery, navigator); + +/** + * Provides a friendly way to create an api client instance using information from the browser's current url + */ +MediaBrowser.ApiClient.create = function (clientName) { + + var loc = window.location; + + return new MediaBrowser.ApiClient(loc.protocol, loc.hostname, loc.port, clientName); +}; \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js b/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js index 5b0685147..47ff3b0c1 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js +++ b/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js @@ -114,31 +114,37 @@ getClientType: function (connection) { - if (connection.Client.toLowerCase() == "dashboard") { + var clientLowered = connection.Client.toLowerCase(); + + if (clientLowered == "dashboard") { return "Dashboard"; } - if (connection.Client.toLowerCase() == "mediabrowsertheater") { + if (clientLowered == "media browser classic") { + + return "Media Browser Classic"; + } + if (clientLowered == "media browser theater") { return "Media Browser Theater"; } - if (connection.Client.toLowerCase() == "android") { + if (clientLowered == "android") { return "Android"; } - if (connection.Client.toLowerCase() == "ios") { + if (clientLowered == "ios") { return "iOS"; } - if (connection.Client.toLowerCase() == "windowsrt") { + if (clientLowered == "windows rt") { return "Windows RT"; } - if (connection.Client.toLowerCase() == "windowsphone") { + if (clientLowered == "windows phone") { return "Windows Phone"; } - if (connection.Client.toLowerCase() == "dlna") { + if (clientLowered == "dlna") { return "Dlna"; } diff --git a/MediaBrowser.WebDashboard/Html/scripts/site.js b/MediaBrowser.WebDashboard/Html/scripts/site.js index 47f0c8508..27dc97810 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/site.js +++ b/MediaBrowser.WebDashboard/Html/scripts/site.js @@ -81,14 +81,14 @@ var Dashboard = { setCurrentUser: function (userId) { localStorage.setItem("userId", userId); - ApiClient.currentUserId = userId; + ApiClient.currentUserId(userId); Dashboard.getUserPromise = null; }, logout: function () { localStorage.removeItem("userId"); Dashboard.getUserPromise = null; - ApiClient.currentUserId = null; + ApiClient.currentUserId(null); window.location = "login.html"; }, @@ -857,7 +857,7 @@ var Dashboard = { systemInfo = systemInfo || Dashboard.lastSystemInfo; - var url = "ws://" + ApiClient.serverHostName + ":" + systemInfo.WebSocketPortNumber + "/mediabrowser"; + var url = "ws://" + ApiClient.serverHostName() + ":" + systemInfo.WebSocketPortNumber + "/mediabrowser"; var ws = new WebSocket(url); @@ -1171,6 +1171,8 @@ var Dashboard = { }; +var ApiClient = MediaBrowser.ApiClient.create("Dashboard"); + $(function () { var footerHtml = '