using MediaBrowser.Model.Authentication; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Weather; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; namespace MediaBrowser.ApiInteraction.Portable { public class ApiClient : BaseApiClient { private HttpWebRequest GetNewRequest(string url) { return HttpWebRequest.CreateHttp(url); } /// /// Gets an image stream based on a url /// public void GetImageStreamAsync(string url, Action callback) { GetStreamAsync(url, callback); } /// /// Gets an image stream based on a url /// private void GetStreamAsync(string url, Action callback) { HttpWebRequest request = GetNewRequest(url); request.BeginGetResponse(new AsyncCallback(result => { using (WebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result)) { Stream stream = response.GetResponseStream(); callback(stream); } }), request); } /// /// Gets a BaseItem /// public void GetItemAsync(Guid id, Guid userId, Action callback) { string url = ApiUrl + "/item?userId=" + userId.ToString(); if (id != Guid.Empty) { url += "&id=" + id.ToString(); } GetDataAsync(url, callback); } /// /// Gets all users /// public void GetAllUsersAsync(Action callback) { string url = ApiUrl + "/users"; GetDataAsync(url, callback); } /// /// Gets all Genres /// public void GetAllGenresAsync(Guid userId, Action callback) { string url = ApiUrl + "/genres?userId=" + userId.ToString(); GetDataAsync(url, callback); } /// /// Gets in-progress items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public void GetInProgressItemsItemsAsync(Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=inprogressitems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets recently added items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public void GetRecentlyAddedItemsAsync(Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=recentlyaddeditems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets favorite items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public void GetFavoriteItemsAsync(Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=favorites&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets recently added items that are unplayed. /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public void GetRecentlyAddedUnplayedItemsAsync(Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=recentlyaddedunplayeditems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets all Years /// public void GetAllYearsAsync(Guid userId, Action callback) { string url = ApiUrl + "/years?userId=" + userId.ToString(); GetDataAsync(url, callback); } /// /// Gets all items that contain a given Year /// public void GetItemsWithYearAsync(string name, Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets all items that contain a given Genre /// public void GetItemsWithGenreAsync(string name, Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets all items that contain a given Person /// public void GetItemsWithPersonAsync(string name, Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets all items that contain a given Person /// public void GetItemsWithPersonAsync(string name, string personType, Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } url += "&persontype=" + personType; GetDataAsync(url, callback); } /// /// Gets all studious /// public void GetAllStudiosAsync(Guid userId, Action callback) { string url = ApiUrl + "/studios?userId=" + userId.ToString(); GetDataAsync(url, callback); } /// /// Gets all items that contain a given Studio /// public void GetItemsWithStudioAsync(string name, Guid userId, Action callback, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } GetDataAsync(url, callback); } /// /// Gets a studio /// public void GetStudioAsync(Guid userId, string name, Action callback) { string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name; GetDataAsync(url, callback); } /// /// Gets a genre /// public void GetGenreAsync(Guid userId, string name, Action callback) { string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name; GetDataAsync(url, callback); } /// /// Gets a person /// public void GetPersonAsync(Guid userId, string name, Action callback) { string url = ApiUrl + "/person?userId=" + userId.ToString() + "&name=" + name; GetDataAsync(url, callback); } /// /// Gets a year /// public void GetYearAsync(Guid userId, int year, Action callback) { string url = ApiUrl + "/year?userId=" + userId.ToString() + "&year=" + year; GetDataAsync(url, callback); } /// /// Gets a list of plugins installed on the server /// public void GetInstalledPluginsAsync(Action callback) { string url = ApiUrl + "/plugins"; GetDataAsync(url, callback); } /// /// Gets a list of plugins installed on the server /// public void GetPluginAssemblyAsync(PluginInfo plugin, Action callback) { string url = ApiUrl + "/pluginassembly?assemblyfilename=" + plugin.AssemblyFileName; GetStreamAsync(url, callback); } /// /// Gets the current server configuration /// public void GetServerConfigurationAsync(Action callback) { string url = ApiUrl + "/ServerConfiguration"; GetDataAsync(url, callback); } /// /// Gets weather information for the default location as set in configuration /// public void GetPluginConfigurationAsync(PluginInfo plugin, Type configurationType, Action callback) { string url = ApiUrl + "/PluginConfiguration?assemblyfilename=" + plugin.AssemblyFileName; // At the moment this can't be retrieved in protobuf format SerializationFormats format = DataSerializer.CanDeSerializeJsv ? SerializationFormats.Jsv : SerializationFormats.Json; GetDataAsync(url, callback, configurationType, format); } /// /// Gets the default user /// public void GetDefaultUserAsync(Action callback) { string url = ApiUrl + "/user"; GetDataAsync(url, callback); } /// /// Gets a user by id /// public void GetUserAsync(Guid id, Action callback) { string url = ApiUrl + "/user?id=" + id.ToString(); GetDataAsync(url, callback); } /// /// Gets weather information for the default location as set in configuration /// public void GetWeatherInfoAsync(Action callback) { string url = ApiUrl + "/weather"; GetDataAsync(url, callback); } /// /// Gets weather information for a specific zip code /// public void GetWeatherInfoAsync(string zipCode, Action callback) { string url = ApiUrl + "/weather?zipcode=" + zipCode; GetDataAsync(url, callback); } /// /// Authenticates a user and returns the result /// public void AuthenticateUserAsync(Guid userId, string password, Action callback) { string url = ApiUrl + "/UserAuthentication?dataformat=" + SerializationFormat.ToString(); Dictionary formValues = new Dictionary(); formValues["userid"] = userId.ToString(); if (!string.IsNullOrEmpty(password)) { formValues["password"] = password; } PostDataAsync(url, formValues, callback, SerializationFormat); } /// /// Updates a user's favorite status for an item and returns the updated UserItemData object. /// public void UpdateFavoriteStatusAsync(Guid itemId, Guid userId, bool isFavorite, Action callback) { string url = ApiUrl + "/favoritestatus?id=" + itemId; url += "&userid=" + userId; url += "&isfavorite=" + (isFavorite ? "1" : "0"); GetDataAsync(url, callback); } /// /// Clears a user's rating for an item /// public void ClearUserItemRatingAsync(Guid itemId, Guid userId, Action callback) { string url = ApiUrl + "/UserItemRating?id=" + itemId; url += "&userid=" + userId; url += "&clear=1"; GetDataAsync(url, callback); } /// /// Updates a user's rating for an item, based on likes or dislikes /// public void UpdateUserItemRatingAsync(Guid itemId, Guid userId, bool likes, Action callback) { string url = ApiUrl + "/UserItemRating?id=" + itemId; url += "&userid=" + userId; url += "&likes=" + (likes ? "1" : "0"); GetDataAsync(url, callback); } /// /// Performs a GET request, and deserializes the response stream to an object of Type T /// private void GetDataAsync(string url, Action callback) where T : class { GetDataAsync(url, callback, SerializationFormat); } /// /// Performs a GET request, and deserializes the response stream to an object of Type T /// private void GetDataAsync(string url, Action callback, SerializationFormats serializationFormat) where T : class { if (url.IndexOf('?') == -1) { url += "?dataformat=" + serializationFormat.ToString(); } else { url += "&dataformat=" + serializationFormat.ToString(); } HttpWebRequest request = GetNewRequest(url); request.BeginGetResponse(new AsyncCallback(result => { T value; using (WebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result)) { using (Stream stream = response.GetResponseStream()) { value = DeserializeFromStream(stream); } } callback(value); }), request); } /// /// Performs a GET request, and deserializes the response stream to an object of Type T /// private void GetDataAsync(string url, Action callback, Type type, SerializationFormats serializationFormat) { if (url.IndexOf('?') == -1) { url += "?dataformat=" + serializationFormat.ToString(); } else { url += "&dataformat=" + serializationFormat.ToString(); } HttpWebRequest request = GetNewRequest(url); request.BeginGetResponse(new AsyncCallback(result => { object value; using (WebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result)) { using (Stream stream = response.GetResponseStream()) { value = DataSerializer.DeserializeFromStream(stream, serializationFormat, type); } } callback(value); }), request); } /// /// Performs a POST request, and deserializes the response stream to an object of Type T /// private void PostDataAsync(string url, Dictionary formValues, Action callback, SerializationFormats serializationFormat) where T : class { if (url.IndexOf('?') == -1) { url += "?dataformat=" + serializationFormat.ToString(); } else { url += "&dataformat=" + serializationFormat.ToString(); } HttpWebRequest request = GetNewRequest(url); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; // Begin getting request stream request.BeginGetRequestStream(new AsyncCallback(beginGetRequestStreamResult => { // Once we have the request stream, write the post data using (Stream requestStream = request.EndGetRequestStream(beginGetRequestStreamResult)) { // Construct the body string postBody = string.Join("&", formValues.Keys.Select(s => string.Format("{0}={1}", s, formValues[s])).ToArray()); // Convert the string into a byte array. byte[] byteArray = Encoding.UTF8.GetBytes(postBody); // Write to the request stream. requestStream.Write(byteArray, 0, byteArray.Length); } // Begin getting response stream request.BeginGetResponse(new AsyncCallback(result => { // Once we have it, deserialize the data and execute the callback T value; using (WebResponse response = request.EndGetResponse(result)) { using (Stream responseStream = response.GetResponseStream()) { value = DeserializeFromStream(responseStream); } } callback(value); }), null); }), null); } } }