Added some favorites api calls

This commit is contained in:
LukePulverenti Luke Pulverenti luke pulverenti 2012-09-09 14:32:51 -04:00
parent fd9ba20451
commit c1c4c85fc2
15 changed files with 316 additions and 48 deletions

View File

@ -171,7 +171,7 @@ namespace MediaBrowser.Api
dto.Type = item.GetType().Name;
dto.UserRating = item.UserRating;
dto.UserData = item.GetUserData(user);
dto.UserData = GetDTOUserItemData(item.GetUserData(user));
Folder folder = item as Folder;
@ -394,6 +394,26 @@ namespace MediaBrowser.Api
};
}
/// <summary>
/// Converts a UserItemData to a DTOUserItemData
/// </summary>
public static DTOUserItemData GetDTOUserItemData(UserItemData data)
{
if (data == null)
{
return null;
}
return new DTOUserItemData()
{
IsFavorite = data.IsFavorite,
Likes = data.Likes,
PlaybackPositionTicks = data.PlaybackPositionTicks,
PlayCount = data.PlayCount,
Rating = data.Rating
};
}
public static bool IsApiUrlMatch(string url, HttpListenerRequest request)
{
url = "/api/" + url;

View File

@ -0,0 +1,44 @@
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Model.DTO;
using MediaBrowser.Model.Entities;
using System.ComponentModel.Composition;
using System.Net;
using System.Threading.Tasks;
namespace MediaBrowser.Api.HttpHandlers
{
/// <summary>
/// Provides a handler to set user favorite status for an item
/// </summary>
[Export(typeof(BaseHandler))]
public class FavoriteStatus : BaseSerializationHandler<DTOUserItemData>
{
public override bool HandlesRequest(HttpListenerRequest request)
{
return ApiService.IsApiUrlMatch("FavoriteStatus", request);
}
protected override Task<DTOUserItemData> GetObjectToSerialize()
{
// Get the item
BaseItem item = ApiService.GetItemById(QueryString["id"]);
// Get the user
User user = ApiService.GetUserById(QueryString["userid"], true);
// Get the user data for this item
UserItemData data = item.GetUserData(user);
if (data == null)
{
data = new UserItemData();
item.AddUserData(user, data);
}
// Set favorite status
data.IsFavorite = QueryString["isfavorite"] == "1";
return Task.FromResult<DTOUserItemData>(ApiService.GetDTOUserItemData(data));
}
}
}

View File

@ -7,6 +7,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.HttpHandlers
{
/// <summary>
/// Provides a handler to retrieve a single item
/// </summary>
[Export(typeof(BaseHandler))]
public class ItemHandler : BaseSerializationHandler<DTOBaseItem>
{
@ -19,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
{
User user = ApiService.GetUserById(QueryString["userid"], true);
BaseItem item = ItemToSerialize;
BaseItem item = ApiService.GetItemById(QueryString["id"]);
if (item == null)
{
@ -28,13 +31,5 @@ namespace MediaBrowser.Api.HttpHandlers
return ApiService.GetDTOBaseItem(item, user);
}
protected virtual BaseItem ItemToSerialize
{
get
{
return ApiService.GetItemById(QueryString["id"]);
}
}
}
}

View File

@ -17,7 +17,7 @@ namespace MediaBrowser.Api.HttpHandlers
{
return ApiService.IsApiUrlMatch("itemlist", request);
}
protected override Task<DTOBaseItem[]> GetObjectToSerialize()
{
User user = ApiService.GetUserById(QueryString["userid"], true);
@ -60,6 +60,10 @@ namespace MediaBrowser.Api.HttpHandlers
{
return parent.GetItemsWithPerson(QueryString["name"], null, user);
}
else if (ListType.Equals("favorites", StringComparison.OrdinalIgnoreCase))
{
return parent.GetFavoriteItems(user);
}
throw new InvalidOperationException();
}

View File

@ -60,6 +60,7 @@
<Compile Include="ApiService.cs" />
<Compile Include="HttpHandlers\AudioHandler.cs" />
<Compile Include="HttpHandlers\BaseMediaHandler.cs" />
<Compile Include="HttpHandlers\FavoriteStatusHandler.cs" />
<Compile Include="HttpHandlers\UserHandler.cs" />
<Compile Include="HttpHandlers\GenreHandler.cs" />
<Compile Include="HttpHandlers\GenresHandler.cs" />

View File

@ -19,7 +19,6 @@ namespace MediaBrowser.ApiInteraction
{
if (format == ApiInteraction.SerializationFormats.Protobuf)
{
//return Serializer.Deserialize<T>(stream);
return ProtobufModelSerializer.Deserialize(stream, null, typeof(T)) as T;
}
else if (format == ApiInteraction.SerializationFormats.Jsv)
@ -44,7 +43,6 @@ namespace MediaBrowser.ApiInteraction
{
if (format == ApiInteraction.SerializationFormats.Protobuf)
{
//throw new NotImplementedException();
return ProtobufModelSerializer.Deserialize(stream, null, type);
}
else if (format == ApiInteraction.SerializationFormats.Jsv)

View File

@ -113,6 +113,23 @@ namespace MediaBrowser.ApiInteraction.Portable
GetDataAsync(url, callback);
}
/// <summary>
/// Gets favorite items
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public void GetFavoriteItemsAsync(Guid userId, Action<DTOBaseItem[]> callback, Guid? folderId = null)
{
string url = ApiUrl + "/itemlist?listtype=favorites&userId=" + userId.ToString();
if (folderId.HasValue)
{
url += "&id=" + folderId.ToString();
}
GetDataAsync(url, callback);
}
/// <summary>
/// Gets recently added items that are unplayed.
/// </summary>
@ -143,29 +160,29 @@ namespace MediaBrowser.ApiInteraction.Portable
/// <summary>
/// Gets all items that contain a given Year
/// </summary>
public void GetItemsWithYearAsync(string name, Guid userId, Action<DTOBaseItem[]> callback)
public void GetItemsWithYearAsync(string name, Guid userId, Action<DTOBaseItem[]> 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);
}
/// <summary>
/// Gets all items that contain a given Genre
/// </summary>
public void GetItemsWithGenreAsync(string name, Guid userId, Action<DTOBaseItem[]> callback)
public void GetItemsWithGenreAsync(string name, Guid userId, Action<DTOBaseItem[]> callback, Guid? folderId = null)
{
string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name;
GetDataAsync(url, callback);
}
/// <summary>
/// Gets all items that contain a given Person
/// </summary>
public void GetItemsWithPersonAsync(string name, Guid userId, Action<DTOBaseItem[]> callback)
{
string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name;
if (folderId.HasValue)
{
url += "&id=" + folderId.ToString();
}
GetDataAsync(url, callback);
}
@ -173,10 +190,30 @@ namespace MediaBrowser.ApiInteraction.Portable
/// <summary>
/// Gets all items that contain a given Person
/// </summary>
public void GetItemsWithPersonAsync(string name, string personType, Guid userId, Action<DTOBaseItem[]> callback)
public void GetItemsWithPersonAsync(string name, Guid userId, Action<DTOBaseItem[]> 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);
}
/// <summary>
/// Gets all items that contain a given Person
/// </summary>
public void GetItemsWithPersonAsync(string name, string personType, Guid userId, Action<DTOBaseItem[]> 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);
@ -195,10 +232,15 @@ namespace MediaBrowser.ApiInteraction.Portable
/// <summary>
/// Gets all items that contain a given Studio
/// </summary>
public void GetItemsWithStudioAsync(string name, Guid userId, Action<DTOBaseItem[]> callback)
public void GetItemsWithStudioAsync(string name, Guid userId, Action<DTOBaseItem[]> 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);
}
@ -344,6 +386,19 @@ namespace MediaBrowser.ApiInteraction.Portable
PostDataAsync(url, formValues, callback, SerializationFormat);
}
/// <summary>
/// Updates a user's favorite status for an item and returns the updated UserItemData object.
/// </summary>
public void UpdateFavoriteStatusAsync(Guid itemId, Guid userId, bool isFavorite, Action<DTOUserItemData> callback)
{
string url = ApiUrl + "/favoritestatus?id=" + itemId;
url += "&userid=" + userId;
url += "&isfavorite=" + (isFavorite ? "1" : "0");
GetDataAsync(url, callback);
}
/// <summary>
/// Performs a GET request, and deserializes the response stream to an object of Type T
/// </summary>

View File

@ -8,6 +8,7 @@ using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.ApiInteraction
{
@ -118,6 +119,26 @@ namespace MediaBrowser.ApiInteraction
}
}
/// <summary>
/// Gets favorite items
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
}
}
/// <summary>
/// Gets recently added items that are unplayed.
/// </summary>
@ -154,10 +175,16 @@ namespace MediaBrowser.ApiInteraction
/// <summary>
/// Gets all items that contain a given Year
/// </summary>
public async Task<DTOBaseItem[]> GetItemsWithYearAsync(string name, Guid userId)
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
@ -167,10 +194,16 @@ namespace MediaBrowser.ApiInteraction
/// <summary>
/// Gets all items that contain a given Genre
/// </summary>
public async Task<DTOBaseItem[]> GetItemsWithGenreAsync(string name, Guid userId)
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
@ -180,10 +213,16 @@ namespace MediaBrowser.ApiInteraction
/// <summary>
/// Gets all items that contain a given Person
/// </summary>
public async Task<DTOBaseItem[]> GetItemsWithPersonAsync(string name, Guid userId)
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
@ -193,12 +232,18 @@ namespace MediaBrowser.ApiInteraction
/// <summary>
/// Gets all items that contain a given Person
/// </summary>
public async Task<DTOBaseItem[]> GetItemsWithPersonAsync(string name, string personType, Guid userId)
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
@ -221,10 +266,16 @@ namespace MediaBrowser.ApiInteraction
/// <summary>
/// Gets all items that contain a given Studio
/// </summary>
public async Task<DTOBaseItem[]> GetItemsWithStudioAsync(string name, Guid userId)
/// <param name="folderId">(Optional) Specify a folder Id to localize the search to a specific folder.</param>
public async Task<DTOBaseItem[]> 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<DTOBaseItem[]>(stream);
@ -387,6 +438,22 @@ namespace MediaBrowser.ApiInteraction
}
}
/// <summary>
/// Updates a user's favorite status for an item and returns the updated UserItemData object.
/// </summary>
public async Task<DTOUserItemData> 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<DTOUserItemData>(stream);
}
}
/// <summary>
/// Authenticates a user and returns the result
/// </summary>

View File

@ -1,7 +1,7 @@
using System.ComponentModel.Composition;
using System.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System.ComponentModel.Composition;
using System.IO;
namespace MediaBrowser.Controller.Resolvers
{

View File

@ -145,7 +145,7 @@ namespace MediaBrowser.Model.DTO
/// User data for this item based on the user it's being requested for
/// </summary>
[ProtoMember(40)]
public UserItemData UserData { get; set; }
public DTOUserItemData UserData { get; set; }
[ProtoMember(41)]
public ItemSpecialCounts SpecialCounts { get; set; }

View File

@ -0,0 +1,23 @@
using ProtoBuf;
namespace MediaBrowser.Model.DTO
{
[ProtoContract]
public class DTOUserItemData
{
[ProtoMember(1)]
public float? Rating { get; set; }
[ProtoMember(2)]
public long PlaybackPositionTicks { get; set; }
[ProtoMember(3)]
public int PlayCount { get; set; }
[ProtoMember(4)]
public bool IsFavorite { get; set; }
[ProtoMember(5)]
public bool? Likes { get; set; }
}
}

View File

@ -2,7 +2,7 @@
namespace MediaBrowser.Model.DTO
{
/// <summary>
/// These are the audio output formats that the api is cabaple of streaming
/// These are the video output formats that the api is cabaple of streaming
/// This does not limit the inputs, only the outputs.
/// </summary>
public enum VideoOutputFormats

View File

@ -96,6 +96,24 @@ namespace MediaBrowser.Model.Entities
return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase)));
}
/// <summary>
/// Finds all recursive items within a top-level parent that the user has marked as a favorite
/// </summary>
public IEnumerable<BaseItem> GetFavoriteItems(User user)
{
return GetParentalAllowedRecursiveChildren(user).Where(c =>
{
UserItemData data = c.GetUserData(user);
if (data != null)
{
return data.IsFavorite;
}
return false;
});
}
/// <summary>
/// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user
/// </summary>

View File

@ -1,25 +1,67 @@
using System;
using ProtoBuf;
using System.Runtime.Serialization;
namespace MediaBrowser.Model.Entities
{
[ProtoContract]
public class UserItemData
{
[ProtoMember(1)]
public UserItemRating Rating { get; set; }
private float? _Rating = null;
/// <summary>
/// Gets or sets the users 0-10 rating
/// </summary>
public float? Rating
{
get
{
return _Rating;
}
set
{
if (value.HasValue)
{
if (value.Value < 0 || value.Value > 10)
{
throw new InvalidOperationException("A 0-10 rating is required for UserItemData.");
}
}
_Rating = value;
}
}
[ProtoMember(2)]
public long PlaybackPositionTicks { get; set; }
[ProtoMember(3)]
public int PlayCount { get; set; }
}
public enum UserItemRating
{
Likes,
Dislikes,
Favorite
public bool IsFavorite { get; set; }
/// <summary>
/// This is an interpreted property to indicate likes or dislikes
/// This should never be serialized.
/// </summary>
[IgnoreDataMember]
public bool? Likes
{
get
{
if (Rating != null)
{
return Rating >= 6.5;
}
return null;
}
set
{
if (value.HasValue)
{
Rating = value.Value ? 10 : 1;
}
else
{
Rating = null;
}
}
}
}
}

View File

@ -36,6 +36,7 @@
<Compile Include="Configuration\ServerConfiguration.cs" />
<Compile Include="DTO\AudioInfo.cs" />
<Compile Include="DTO\AudioOutputFormats.cs" />
<Compile Include="DTO\DTOUserItemData.cs" />
<Compile Include="DTO\SeriesInfo.cs" />
<Compile Include="Authentication\AuthenticationResult.cs" />
<Compile Include="DTO\DTOBaseItem.cs" />