using MediaBrowser.Model.Authentication; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Weather; using System; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; #if WINDOWS_PHONE using SharpGIS; #else using System.Net.Http; #endif namespace MediaBrowser.ApiInteraction { /// /// Provides api methods centered around an HttpClient /// public abstract class BaseHttpApiClient : BaseApiClient { #if WINDOWS_PHONE public BaseHttpApiClient() { HttpClient = new GZipWebClient(); } private WebClient HttpClient { get; set; } #else public BaseHttpApiClient(HttpClientHandler handler) : base() { handler.AutomaticDecompression = DecompressionMethods.Deflate; HttpClient = new HttpClient(handler); } private HttpClient HttpClient { get; set; } #endif /// /// Gets an image stream based on a url /// public Task GetImageStreamAsync(string url) { return GetStreamAsync(url); } /// /// Gets a BaseItem /// public async Task GetItemAsync(Guid id, Guid userId) { string url = ApiUrl + "/item?userId=" + userId.ToString(); if (id != Guid.Empty) { url += "&id=" + id.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all Users /// public async Task GetAllUsersAsync() { string url = ApiUrl + "/users"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all Genres /// public async Task GetAllGenresAsync(Guid userId) { string url = ApiUrl + "/genres?userId=" + userId.ToString(); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets in-progress items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetInProgressItemsItemsAsync(Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=inprogressitems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets recently added items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetRecentlyAddedItemsAsync(Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=recentlyaddeditems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets favorite items /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetFavoriteItemsAsync(Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=favorites&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets recently added items that are unplayed. /// /// The user id. /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetRecentlyAddedUnplayedItemsAsync(Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=recentlyaddedunplayeditems&userId=" + userId.ToString(); if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all Years /// public async Task GetAllYearsAsync(Guid userId) { string url = ApiUrl + "/years?userId=" + userId.ToString(); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all items that contain a given Year /// /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetItemsWithYearAsync(string name, Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all items that contain a given Genre /// /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetItemsWithGenreAsync(string name, Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all items that contain a given Person /// /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetItemsWithPersonAsync(string name, Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all items that contain a given Person /// /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetItemsWithPersonAsync(string name, string personType, Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; url += "&persontype=" + personType; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all studious /// public async Task GetAllStudiosAsync(Guid userId) { string url = ApiUrl + "/studios?userId=" + userId.ToString(); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets all items that contain a given Studio /// /// (Optional) Specify a folder Id to localize the search to a specific folder. public async Task GetItemsWithStudioAsync(string name, Guid userId, Guid? folderId = null) { string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name; if (folderId.HasValue) { url += "&id=" + folderId.ToString(); } using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a studio /// public async Task GetStudioAsync(Guid userId, string name) { string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a genre /// public async Task GetGenreAsync(Guid userId, string name) { string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a person /// public async Task GetPersonAsync(Guid userId, string name) { string url = ApiUrl + "/person?userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a year /// public async Task GetYearAsync(Guid userId, int year) { string url = ApiUrl + "/year?userId=" + userId.ToString() + "&year=" + year; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a list of plugins installed on the server /// public async Task GetInstalledPluginsAsync() { string url = ApiUrl + "/plugins"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a list of plugins installed on the server /// public Task GetPluginAssemblyAsync(PluginInfo plugin) { string url = ApiUrl + "/pluginassembly?assemblyfilename=" + plugin.AssemblyFileName; return GetStreamAsync(url); } /// /// Gets the current server configuration /// public async Task GetServerConfigurationAsync() { string url = ApiUrl + "/ServerConfiguration"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets weather information for the default location as set in configuration /// public async Task GetPluginConfigurationAsync(PluginInfo plugin, Type configurationType) { 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; using (Stream stream = await GetSerializedStreamAsync(url, format).ConfigureAwait(false)) { return DataSerializer.DeserializeFromStream(stream, format, configurationType); } } /// /// Gets the default user /// public async Task GetDefaultUserAsync() { string url = ApiUrl + "/user"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets a user by id /// public async Task GetUserAsync(Guid id) { string url = ApiUrl + "/user?id=" + id.ToString(); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets weather information for the default location as set in configuration /// public async Task GetWeatherInfoAsync() { string url = ApiUrl + "/weather"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets weather information for a specific zip code /// public async Task GetWeatherInfoAsync(string zipCode) { string url = ApiUrl + "/weather?zipcode=" + zipCode; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Gets special features for a Movie /// public async Task GetMovieSpecialFeaturesAsync(Guid itemId, Guid userId) { string url = ApiUrl + "/MovieSpecialFeatures?id=" + itemId; url += "&userid=" + userId; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Updates played status for an item /// public async Task UpdatePlayedStatusAsync(Guid itemId, Guid userId, bool wasPlayed) { string url = ApiUrl + "/PlayedStatus?id=" + itemId; url += "&userid=" + userId; url += "&played=" + (wasPlayed ? "1" : "0"); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Updates a user's favorite status for an item and returns the updated UserItemData object. /// public async Task UpdateFavoriteStatusAsync(Guid itemId, Guid userId, bool isFavorite) { string url = ApiUrl + "/favoritestatus?id=" + itemId; url += "&userid=" + userId; url += "&isfavorite=" + (isFavorite ? "1" : "0"); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Clears a user's rating for an item /// public async Task ClearUserItemRatingAsync(Guid itemId, Guid userId) { string url = ApiUrl + "/UserItemRating?id=" + itemId; url += "&userid=" + userId; url += "&clear=1"; using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Updates a user's rating for an item, based on likes or dislikes /// public async Task UpdateUserItemRatingAsync(Guid itemId, Guid userId, bool likes) { string url = ApiUrl + "/UserItemRating?id=" + itemId; url += "&userid=" + userId; url += "&likes=" + (likes ? "1" : "0"); using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) { return DeserializeFromStream(stream); } } /// /// Authenticates a user and returns the result /// public async Task AuthenticateUserAsync(Guid userId, string password) { string url = ApiUrl + "/UserAuthentication?dataformat=" + SerializationFormat.ToString(); // Create the post body string postContent = string.Format("userid={0}", userId); if (!string.IsNullOrEmpty(password)) { postContent += "&password=" + password; } #if WINDOWS_PHONE HttpClient.Headers["Content-Type"] = "application/x-www-form-urlencoded"; var result = await HttpClient.UploadStringTaskAsync(url, "POST", postContent); var byteArray = Encoding.UTF8.GetBytes(result); using (MemoryStream stream = new MemoryStream(byteArray)) { return DeserializeFromStream(stream); } #else HttpContent content = new StringContent(postContent, Encoding.UTF8, "application/x-www-form-urlencoded"); HttpResponseMessage msg = await HttpClient.PostAsync(url, content).ConfigureAwait(false); using (Stream stream = await msg.Content.ReadAsStreamAsync().ConfigureAwait(false)) { return DeserializeFromStream(stream); } #endif } /// /// This is a helper around getting a stream from the server that contains serialized data /// private Task GetSerializedStreamAsync(string url) { return GetSerializedStreamAsync(url, SerializationFormat); } /// /// This is a helper around getting a stream from the server that contains serialized data /// private Task GetSerializedStreamAsync(string url, SerializationFormats serializationFormat) { if (url.IndexOf('?') == -1) { url += "?dataformat=" + serializationFormat.ToString(); } else { url += "&dataformat=" + serializationFormat.ToString(); } return GetStreamAsync(url); } /// /// This is just a helper around HttpClient /// private Task GetStreamAsync(string url) { #if WINDOWS_PHONE return HttpClient.OpenReadTaskAsync(url); #else return HttpClient.GetStreamAsync(url); #endif } public override void Dispose() { #if !WINDOWS_PHONE HttpClient.Dispose(); #endif } } }