diff options
Diffstat (limited to 'MediaBrowser.Api/UserLibrary')
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/ArtistsService.cs | 187 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs | 66 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 7 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/GenresService.cs | 110 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs | 166 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/ItemsService.cs | 9 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/PersonsService.cs | 74 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/StudiosService.cs | 76 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/YearsService.cs | 70 |
9 files changed, 638 insertions, 127 deletions
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs new file mode 100644 index 000000000..2622f0bd1 --- /dev/null +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -0,0 +1,187 @@ +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Querying; +using ServiceStack.ServiceHost; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.UserLibrary +{ + /// <summary> + /// Class GetArtists + /// </summary> + [Route("/Artists", "GET")] + [Api(Description = "Gets all artists from a given item, folder, or the entire library")] + public class GetArtists : GetItemsByName + { + } + + /// <summary> + /// Class GetArtistsItemCounts + /// </summary> + [Route("/Artists/{Name}/Counts", "GET")] + [Api(Description = "Gets item counts of library items that an artist appears in")] + public class GetArtistsItemCounts : IReturn<ItemByNameCounts> + { + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public Guid UserId { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Name { get; set; } + } + + [Route("/Artists/{Name}", "GET")] + [Api(Description = "Gets an artist, by name")] + public class GetArtist : IReturn<BaseItemDto> + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + } + + /// <summary> + /// Class ArtistsService + /// </summary> + public class ArtistsService : BaseItemsByNameService<Artist> + { + /// <summary> + /// Initializes a new instance of the <see cref="ArtistsService"/> class. + /// </summary> + /// <param name="userManager">The user manager.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="userDataRepository">The user data repository.</param> + public ArtistsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository) + : base(userManager, libraryManager, userDataRepository) + { + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetArtist request) + { + var result = GetItem(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{BaseItemDto}.</returns> + private async Task<BaseItemDto> GetItem(GetArtist request) + { + var item = await LibraryManager.GetArtist(request.Name).ConfigureAwait(false); + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)); + + var builder = new DtoBuilder(Logger, LibraryManager, UserDataRepository); + + if (request.UserId.HasValue) + { + var user = UserManager.GetUserById(request.UserId.Value); + + return await builder.GetBaseItemDto(item, user, fields.ToList()).ConfigureAwait(false); + } + + return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false); + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetArtistsItemCounts request) + { + var items = GetItems(request.UserId).OfType<Audio>().Where(i => i.HasArtist(request.Name)).ToList(); + + var counts = new ItemByNameCounts + { + TotalCount = items.Count, + + SongCount = items.Count(), + + AlbumCount = items.Select(i => i.Parent).OfType<MusicAlbum>().Distinct().Count() + }; + + return ToOptimizedResult(counts); + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetArtists request) + { + var result = GetResult(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets all items. + /// </summary> + /// <param name="request">The request.</param> + /// <param name="items">The items.</param> + /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> + protected override IEnumerable<IbnStub<Artist>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) + { + var itemsList = items.OfType<Audio>().ToList(); + + return itemsList + .SelectMany(i => + { + var list = i.Artists.ToList(); + + if (!string.IsNullOrEmpty(i.AlbumArtist)) + { + list.Add(i.AlbumArtist); + } + + return list; + }) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(name => new IbnStub<Artist>(name, () => itemsList.Where(i => i.HasArtist(name)), GetEntity)); + } + + /// <summary> + /// Gets the entity. + /// </summary> + /// <param name="name">The name.</param> + /// <returns>Task{Artist}.</returns> + protected Task<Artist> GetEntity(string name) + { + return LibraryManager.GetArtist(name); + } + } +} diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 0a2d6453a..8f2264c6a 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -50,9 +50,18 @@ namespace MediaBrowser.Api.UserLibrary /// <returns>Task{ItemsResult}.</returns> protected async Task<ItemsResult> GetResult(GetItemsByName request) { - var user = UserManager.GetUserById(request.UserId); + User user = null; + BaseItem item; - var item = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.ParentId, UserManager, LibraryManager, user.Id); + if (request.UserId.HasValue) + { + user = UserManager.GetUserById(request.UserId.Value); + item = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.ParentId, UserManager, LibraryManager, user.Id); + } + else + { + item = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : DtoBuilder.GetItemByClientId(request.ParentId, UserManager, LibraryManager); + } IEnumerable<BaseItem> items; @@ -60,16 +69,23 @@ namespace MediaBrowser.Api.UserLibrary { var folder = (Folder)item; - items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user); + if (request.UserId.HasValue) + { + items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user); + } + else + { + items = request.Recursive ? folder.RecursiveChildren: folder.Children; + } } else { items = new[] { item }; } - items = FilterItems(request, items, user); + items = FilterItems(request, items); - var extractedItems = GetAllItems(request, items, user); + var extractedItems = GetAllItems(request, items); extractedItems = FilterItems(request, extractedItems, user); extractedItems = SortItems(request, extractedItems); @@ -187,9 +203,8 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{BaseItem}.</returns> - private IEnumerable<BaseItem> FilterItems(GetItemsByName request, IEnumerable<BaseItem> items, User user) + private IEnumerable<BaseItem> FilterItems(GetItemsByName request, IEnumerable<BaseItem> items) { // Exclude item types if (!string.IsNullOrEmpty(request.ExcludeItemTypes)) @@ -213,9 +228,8 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> - protected abstract IEnumerable<IbnStub<TItemType>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items, User user); + protected abstract IEnumerable<IbnStub<TItemType>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items); /// <summary> /// Gets the dto. @@ -238,18 +252,36 @@ namespace MediaBrowser.Api.UserLibrary return null; } - var dto = await new DtoBuilder(Logger, LibraryManager, UserDataRepository).GetBaseItemDto(item, user, fields).ConfigureAwait(false); + var dto = user == null ? await new DtoBuilder(Logger, LibraryManager, UserDataRepository).GetBaseItemDto(item, fields).ConfigureAwait(false) : + await new DtoBuilder(Logger, LibraryManager, UserDataRepository).GetBaseItemDto(item, user, fields).ConfigureAwait(false); if (fields.Contains(ItemFields.ItemCounts)) { var items = stub.Items; dto.ChildCount = items.Count; - dto.RecentlyAddedItemCount = items.Count(i => i.IsRecentlyAdded(user)); + dto.RecentlyAddedItemCount = items.Count(i => i.IsRecentlyAdded()); } return dto; } + + /// <summary> + /// Gets the items. + /// </summary> + /// <param name="userId">The user id.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + protected IEnumerable<BaseItem> GetItems(Guid? userId) + { + if (userId.HasValue) + { + var user = UserManager.GetUserById(userId.Value); + + return UserManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user); + } + + return LibraryManager.RootFolder.RecursiveChildren; + } } /// <summary> @@ -258,11 +290,23 @@ namespace MediaBrowser.Api.UserLibrary public class GetItemsByName : BaseItemsRequest, IReturn<ItemsResult> { /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + + /// <summary> /// What to sort the results by /// </summary> /// <value>The sort by.</value> [ApiMember(Name = "SortBy", Description = "Optional. Options: SortName", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string SortBy { get; set; } + + public GetItemsByName() + { + Recursive = true; + } } public class IbnStub<T> diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index afe93a086..7dcce53b2 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -10,13 +10,6 @@ namespace MediaBrowser.Api.UserLibrary public abstract class BaseItemsRequest { /// <summary> - /// Gets or sets the user id. - /// </summary> - /// <value>The user id.</value> - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// <summary> /// Skips over a given number of items within the results. Use for paging. /// </summary> /// <value>The start index.</value> diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 4f87b154e..30094d4f3 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -1,11 +1,12 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; @@ -17,17 +18,13 @@ namespace MediaBrowser.Api.UserLibrary /// <summary> /// Class GetGenres /// </summary> - [Route("/Users/{UserId}/Items/{ParentId}/Genres", "GET")] - [Route("/Users/{UserId}/Items/Root/Genres", "GET")] + [Route("/Genres", "GET")] [Api(Description = "Gets all genres from a given item, folder, or the entire library")] public class GetGenres : GetItemsByName { } - /// <summary> - /// Class GetGenreItemCounts - /// </summary> - [Route("/Users/{UserId}/Genres/{Name}/Counts", "GET")] + [Route("/Genres/{Name}/Counts", "GET")] [Api(Description = "Gets item counts of library items that a genre appears in")] public class GetGenreItemCounts : IReturn<ItemByNameCounts> { @@ -35,8 +32,8 @@ namespace MediaBrowser.Api.UserLibrary /// Gets or sets the user id. /// </summary> /// <value>The user id.</value> - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } /// <summary> /// Gets or sets the name. @@ -45,6 +42,28 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] public string Name { get; set; } } + + /// <summary> + /// Class GetGenre + /// </summary> + [Route("/Genres/{Name}", "GET")] + [Api(Description = "Gets a genre, by name")] + public class GetGenre : IReturn<BaseItemDto> + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + } /// <summary> /// Class GenresService @@ -61,32 +80,37 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public object Get(GetGenreItemCounts request) + public object Get(GetGenre request) { - var user = UserManager.GetUserById(request.UserId); - - var items = user.RootFolder.GetRecursiveChildren(user).Where(i => i.Genres != null && i.Genres.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList(); + var result = GetItem(request).Result; - var counts = new ItemByNameCounts - { - TotalCount = items.Count, - - TrailerCount = items.OfType<Trailer>().Count(), + return ToOptimizedResult(result); + } - MovieCount = items.OfType<Movie>().Count(), + /// <summary> + /// Gets the item. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{BaseItemDto}.</returns> + private async Task<BaseItemDto> GetItem(GetGenre request) + { + var item = await LibraryManager.GetGenre(request.Name).ConfigureAwait(false); - SeriesCount = items.OfType<Series>().Count(), + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)); - GameCount = items.OfType<BaseGame>().Count(), + var builder = new DtoBuilder(Logger, LibraryManager, UserDataRepository); - SongCount = items.OfType<Audio>().Count(), + if (request.UserId.HasValue) + { + var user = UserManager.GetUserById(request.UserId.Value); - AlbumCount = items.OfType<MusicAlbum>().Count() - }; + return await builder.GetBaseItemDto(item, user, fields.ToList()).ConfigureAwait(false); + } - return ToOptimizedResult(counts); + return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false); } - + /// <summary> /// Gets the specified request. /// </summary> @@ -104,9 +128,8 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> - protected override IEnumerable<IbnStub<Genre>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items, User user) + protected override IEnumerable<IbnStub<Genre>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) { var itemsList = items.Where(i => i.Genres != null).ToList(); @@ -125,5 +148,34 @@ namespace MediaBrowser.Api.UserLibrary { return LibraryManager.GetGenre(name); } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetGenreItemCounts request) + { + var items = GetItems(request.UserId).Where(i => i.Genres != null && i.Genres.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList(); + + var counts = new ItemByNameCounts + { + TotalCount = items.Count, + + TrailerCount = items.OfType<Trailer>().Count(), + + MovieCount = items.OfType<Movie>().Count(), + + SeriesCount = items.OfType<Series>().Count(), + + GameCount = items.OfType<BaseGame>().Count(), + + SongCount = items.OfType<Audio>().Count(), + + AlbumCount = items.OfType<MusicAlbum>().Count() + }; + + return ToOptimizedResult(counts); + } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs b/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs index e068eb216..a3f36afe9 100644 --- a/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs @@ -1,6 +1,8 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using ServiceStack.ServiceHost; +using ServiceStack.Text.Controller; using System; using System.Threading; using System.Threading.Tasks; @@ -8,31 +10,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.UserLibrary { /// <summary> - /// Class GetItemByNameUserData - /// </summary> - [Route("/Users/{UserId}/ItemsByName/{Name}/UserData", "GET")] - [Api(Description = "Gets user data for an item")] - public class GetItemByNameUserData : IReturnVoid - { - /// <summary> - /// Gets or sets the user id. - /// </summary> - /// <value>The user id.</value> - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist, album)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - } - - /// <summary> /// Class MarkItemByNameFavorite /// </summary> - [Route("/Users/{UserId}/ItemsByName/Favorites/{Name}", "POST")] + [Route("/Users/{UserId}/Favorites/Artists/{Name}", "POST")] + [Route("/Users/{UserId}/Favorites/Persons/{Name}", "POST")] + [Route("/Users/{UserId}/Favorites/Studios/{Name}", "POST")] + [Route("/Users/{UserId}/Favorites/Genres/{Name}", "POST")] [Api(Description = "Marks something as a favorite")] public class MarkItemByNameFavorite : IReturnVoid { @@ -47,14 +30,17 @@ namespace MediaBrowser.Api.UserLibrary /// Gets or sets the name. /// </summary> /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist, album)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + [ApiMember(Name = "Name", Description = "The name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] public string Name { get; set; } } /// <summary> /// Class UnmarkItemByNameFavorite /// </summary> - [Route("/Users/{UserId}/ItemsByName/Favorites/{Name}", "DELETE")] + [Route("/Users/{UserId}/Favorites/Artists/{Name}", "DELETE")] + [Route("/Users/{UserId}/Favorites/Persons/{Name}", "DELETE")] + [Route("/Users/{UserId}/Favorites/Studios/{Name}", "DELETE")] + [Route("/Users/{UserId}/Favorites/Genres/{Name}", "DELETE")] [Api(Description = "Unmarks something as a favorite")] public class UnmarkItemByNameFavorite : IReturnVoid { @@ -69,11 +55,17 @@ namespace MediaBrowser.Api.UserLibrary /// Gets or sets the name. /// </summary> /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist, album)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] + [ApiMember(Name = "Name", Description = "The name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] public string Name { get; set; } } - [Route("/Users/{UserId}/ItemsByName/{Name}/Rating", "POST")] + /// <summary> + /// Class UpdateItemByNameRating + /// </summary> + [Route("/Users/{UserId}/Ratings/Artists/{Name}", "POST")] + [Route("/Users/{UserId}/Ratings/Persons/{Name}", "POST")] + [Route("/Users/{UserId}/Ratings/Studios/{Name}", "POST")] + [Route("/Users/{UserId}/Ratings/Genres/{Name}", "POST")] [Api(Description = "Updates a user's rating for an item")] public class UpdateItemByNameRating : IReturnVoid { @@ -88,7 +80,7 @@ namespace MediaBrowser.Api.UserLibrary /// Gets or sets the name. /// </summary> /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist, album)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + [ApiMember(Name = "Name", Description = "The name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] public string Name { get; set; } /// <summary> @@ -99,7 +91,13 @@ namespace MediaBrowser.Api.UserLibrary public bool Likes { get; set; } } - [Route("/Users/{UserId}/ItemsByName/{Name}/Rating", "DELETE")] + /// <summary> + /// Class DeleteItemByNameRating + /// </summary> + [Route("/Users/{UserId}/Ratings/Artists/{Name}", "DELETE")] + [Route("/Users/{UserId}/Ratings/Persons/{Name}", "DELETE")] + [Route("/Users/{UserId}/Ratings/Studios/{Name}", "DELETE")] + [Route("/Users/{UserId}/Ratings/Genres/{Name}", "DELETE")] [Api(Description = "Deletes a user's saved personal rating for an item")] public class DeleteItemByNameRating : IReturnVoid { @@ -114,10 +112,10 @@ namespace MediaBrowser.Api.UserLibrary /// Gets or sets the name. /// </summary> /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist, album)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] + [ApiMember(Name = "Name", Description = "The item name (genre, person, year, studio, artist)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] public string Name { get; set; } } - + /// <summary> /// Class ItemByNameUserDataService /// </summary> @@ -129,34 +127,31 @@ namespace MediaBrowser.Api.UserLibrary protected readonly IUserDataRepository UserDataRepository; /// <summary> + /// The library manager + /// </summary> + protected readonly ILibraryManager LibraryManager; + + /// <summary> /// Initializes a new instance of the <see cref="ItemByNameUserDataService" /> class. /// </summary> /// <param name="userDataRepository">The user data repository.</param> - public ItemByNameUserDataService(IUserDataRepository userDataRepository) + /// <param name="libraryManager">The library manager.</param> + public ItemByNameUserDataService(IUserDataRepository userDataRepository, ILibraryManager libraryManager) { UserDataRepository = userDataRepository; + LibraryManager = libraryManager; } /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Get(GetItemByNameUserData request) - { - // Get the user data for this item - var data = UserDataRepository.GetUserData(request.UserId, request.Name).Result; - - return ToOptimizedResult(DtoBuilder.GetUserItemDataDto(data)); - } - - /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> public void Post(MarkItemByNameFavorite request) { - var task = MarkFavorite(request.UserId, request.Name, true); + var pathInfo = PathInfo.Parse(RequestContext.PathInfo); + var type = pathInfo.GetArgumentValue<string>(3); + + var task = MarkFavorite(request.UserId, type, request.Name, true); Task.WaitAll(task); } @@ -167,18 +162,24 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="request">The request.</param> public void Post(UpdateItemByNameRating request) { - var task = MarkLike(request.UserId, request.Name, request.Likes); + var pathInfo = PathInfo.Parse(RequestContext.PathInfo); + var type = pathInfo.GetArgumentValue<string>(3); + + var task = MarkLike(request.UserId, type, request.Name, request.Likes); Task.WaitAll(task); } - + /// <summary> /// Deletes the specified request. /// </summary> /// <param name="request">The request.</param> public void Delete(UnmarkItemByNameFavorite request) { - var task = MarkFavorite(request.UserId, request.Name, false); + var pathInfo = PathInfo.Parse(RequestContext.PathInfo); + var type = pathInfo.GetArgumentValue<string>(3); + + var task = MarkFavorite(request.UserId, type, request.Name, false); Task.WaitAll(task); } @@ -189,7 +190,10 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="request">The request.</param> public void Delete(DeleteItemByNameRating request) { - var task = MarkLike(request.UserId, request.Name, null); + var pathInfo = PathInfo.Parse(RequestContext.PathInfo); + var type = pathInfo.GetArgumentValue<string>(3); + + var task = MarkLike(request.UserId, type, request.Name, null); Task.WaitAll(task); } @@ -198,11 +202,37 @@ namespace MediaBrowser.Api.UserLibrary /// Marks the favorite. /// </summary> /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> + /// <param name="type">The type.</param> + /// <param name="name">The name.</param> /// <param name="isFavorite">if set to <c>true</c> [is favorite].</param> /// <returns>Task.</returns> - protected async Task MarkFavorite(Guid userId, string key, bool isFavorite) + protected async Task MarkFavorite(Guid userId, string type, string name, bool isFavorite) { + BaseItem item; + + if (string.Equals(type, "Persons")) + { + item = await LibraryManager.GetPerson(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Artists")) + { + item = await LibraryManager.GetArtist(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Genres")) + { + item = await LibraryManager.GetGenre(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Studios")) + { + item = await LibraryManager.GetStudio(name).ConfigureAwait(false); + } + else + { + throw new ArgumentException(); + } + + var key = item.GetUserDataKey(); + // Get the user data for this item var data = await UserDataRepository.GetUserData(userId, key).ConfigureAwait(false); @@ -216,11 +246,37 @@ namespace MediaBrowser.Api.UserLibrary /// Marks the like. /// </summary> /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> + /// <param name="type">The type.</param> + /// <param name="name">The name.</param> /// <param name="likes">if set to <c>true</c> [likes].</param> /// <returns>Task.</returns> - protected async Task MarkLike(Guid userId, string key, bool? likes) + protected async Task MarkLike(Guid userId, string type, string name, bool? likes) { + BaseItem item; + + if (string.Equals(type, "Persons")) + { + item = await LibraryManager.GetPerson(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Artists")) + { + item = await LibraryManager.GetArtist(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Genres")) + { + item = await LibraryManager.GetGenre(name).ConfigureAwait(false); + } + else if (string.Equals(type, "Studios")) + { + item = await LibraryManager.GetStudio(name).ConfigureAwait(false); + } + else + { + throw new ArgumentException(); + } + + var key = item.GetUserDataKey(); + // Get the user data for this item var data = await UserDataRepository.GetUserData(userId, key).ConfigureAwait(false); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 79e00998f..7d3581846 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -22,6 +22,13 @@ namespace MediaBrowser.Api.UserLibrary public class GetItems : BaseItemsRequest, IReturn<ItemsResult> { /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public Guid UserId { get; set; } + + /// <summary> /// Limit results to items containing a specific person /// </summary> /// <value>The person.</value> @@ -328,7 +335,7 @@ namespace MediaBrowser.Api.UserLibrary }); case ItemFilter.IsRecentlyAdded: - return items.Where(item => item.IsRecentlyAdded(currentUser)); + return items.Where(item => item.IsRecentlyAdded()); case ItemFilter.IsResumable: return items.Where(item => diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index fb623e953..ee16a986e 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; @@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; @@ -17,8 +19,7 @@ namespace MediaBrowser.Api.UserLibrary /// <summary> /// Class GetPersons /// </summary> - [Route("/Users/{UserId}/Items/{ParentId}/Persons", "GET")] - [Route("/Users/{UserId}/Items/Root/Persons", "GET")] + [Route("/Persons", "GET")] [Api(Description = "Gets all persons from a given item, folder, or the entire library")] public class GetPersons : GetItemsByName { @@ -32,7 +33,7 @@ namespace MediaBrowser.Api.UserLibrary /// <summary> /// Class GetPersonItemCounts /// </summary> - [Route("/Users/{UserId}/Persons/{Name}/Counts", "GET")] + [Route("/Persons/{Name}/Counts", "GET")] [Api(Description = "Gets item counts of library items that a person appears in")] public class GetPersonItemCounts : IReturn<ItemByNameCounts> { @@ -52,6 +53,28 @@ namespace MediaBrowser.Api.UserLibrary } /// <summary> + /// Class GetPerson + /// </summary> + [Route("/Persons/{Name}", "GET")] + [Api(Description = "Gets a person, by name")] + public class GetPerson : IReturn<BaseItemDto> + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + [ApiMember(Name = "Name", Description = "The person name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + } + + /// <summary> /// Class PersonsService /// </summary> public class PersonsService : BaseItemsByNameService<Person> @@ -72,6 +95,42 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> + public object Get(GetPerson request) + { + var result = GetItem(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{BaseItemDto}.</returns> + private async Task<BaseItemDto> GetItem(GetPerson request) + { + var item = await LibraryManager.GetPerson(request.Name).ConfigureAwait(false); + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)); + + var builder = new DtoBuilder(Logger, LibraryManager, UserDataRepository); + + if (request.UserId.HasValue) + { + var user = UserManager.GetUserById(request.UserId.Value); + + return await builder.GetBaseItemDto(item, user, fields.ToList()).ConfigureAwait(false); + } + + return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false); + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> public object Get(GetPersons request) { var result = GetResult(request).Result; @@ -86,9 +145,7 @@ namespace MediaBrowser.Api.UserLibrary /// <returns>System.Object.</returns> public object Get(GetPersonItemCounts request) { - var user = UserManager.GetUserById(request.UserId); - - var items = user.RootFolder.GetRecursiveChildren(user).Where(i => i.People != null && i.People.Any(p => string.Equals(p.Name, request.Name, StringComparison.OrdinalIgnoreCase))).ToList(); + var items = GetItems(request.UserId).Where(i => i.People != null && i.People.Any(p => string.Equals(p.Name, request.Name, StringComparison.OrdinalIgnoreCase))).ToList(); var counts = new ItemByNameCounts { @@ -117,9 +174,8 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> - protected override IEnumerable<IbnStub<Person>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items, User user) + protected override IEnumerable<IbnStub<Person>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) { var inputPersonTypes = ((GetPersons)request).PersonTypes; var personTypes = string.IsNullOrEmpty(inputPersonTypes) ? new string[] { } : inputPersonTypes.Split(','); diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 94c604685..4e3a2d42a 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -1,10 +1,12 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Querying; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; @@ -16,14 +18,13 @@ namespace MediaBrowser.Api.UserLibrary /// <summary> /// Class GetStudios /// </summary> - [Route("/Users/{UserId}/Items/{ParentId}/Studios", "GET")] - [Route("/Users/{UserId}/Items/Root/Studios", "GET")] + [Route("/Studios", "GET")] [Api(Description = "Gets all studios from a given item, folder, or the entire library")] public class GetStudios : GetItemsByName { } - [Route("/Users/{UserId}/Studios/{Name}/Counts", "GET")] + [Route("/Studios/{Name}/Counts", "GET")] [Api(Description = "Gets item counts of library items that a studio appears in")] public class GetStudioItemCounts : IReturn<ItemByNameCounts> { @@ -43,6 +44,28 @@ namespace MediaBrowser.Api.UserLibrary } /// <summary> + /// Class GetStudio + /// </summary> + [Route("/Studios/{Name}", "GET")] + [Api(Description = "Gets a studio, by name")] + public class GetStudio : IReturn<BaseItemDto> + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + [ApiMember(Name = "Name", Description = "The studio name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + } + + /// <summary> /// Class StudiosService /// </summary> public class StudiosService : BaseItemsByNameService<Studio> @@ -57,11 +80,45 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> - public object Get(GetStudioItemCounts request) + public object Get(GetStudio request) + { + var result = GetItem(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{BaseItemDto}.</returns> + private async Task<BaseItemDto> GetItem(GetStudio request) { - var user = UserManager.GetUserById(request.UserId); + var item = await LibraryManager.GetStudio(request.Name).ConfigureAwait(false); + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)); + + var builder = new DtoBuilder(Logger, LibraryManager, UserDataRepository); + + if (request.UserId.HasValue) + { + var user = UserManager.GetUserById(request.UserId.Value); + + return await builder.GetBaseItemDto(item, user, fields.ToList()).ConfigureAwait(false); + } - var items = user.RootFolder.GetRecursiveChildren(user).Where(i => i.Studios != null && i.Studios.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList(); + return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false); + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetStudioItemCounts request) + { + var items = GetItems(request.UserId).Where(i => i.Studios != null && i.Studios.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList(); var counts = new ItemByNameCounts { @@ -94,15 +151,14 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - + /// <summary> /// Gets all items. /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> - protected override IEnumerable<IbnStub<Studio>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items, User user) + protected override IEnumerable<IbnStub<Studio>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) { var itemsList = items.Where(i => i.Studios != null).ToList(); diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index b22a8dac3..79cb08ef9 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -1,7 +1,11 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Querying; using ServiceStack.ServiceHost; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -12,14 +16,35 @@ namespace MediaBrowser.Api.UserLibrary /// <summary> /// Class GetYears /// </summary> - [Route("/Users/{UserId}/Items/{ParentId}/Years", "GET")] - [Route("/Users/{UserId}/Items/Root/Years", "GET")] + [Route("/Years", "GET")] [Api(Description = "Gets all years from a given item, folder, or the entire library")] public class GetYears : GetItemsByName { } /// <summary> + /// Class GetYear + /// </summary> + [Route("/Years/{Year}", "GET")] + [Api(Description = "Gets a year")] + public class GetYear : IReturn<BaseItemDto> + { + /// <summary> + /// Gets or sets the year. + /// </summary> + /// <value>The year.</value> + [ApiMember(Name = "Year", Description = "The year", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] + public int Year { get; set; } + + /// <summary> + /// Gets or sets the user id. + /// </summary> + /// <value>The user id.</value> + [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? UserId { get; set; } + } + + /// <summary> /// Class YearsService /// </summary> public class YearsService : BaseItemsByNameService<Year> @@ -39,6 +64,42 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <returns>System.Object.</returns> + public object Get(GetYear request) + { + var result = GetItem(request).Result; + + return ToOptimizedResult(result); + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{BaseItemDto}.</returns> + private async Task<BaseItemDto> GetItem(GetYear request) + { + var item = await LibraryManager.GetYear(request.Year).ConfigureAwait(false); + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)); + + var builder = new DtoBuilder(Logger, LibraryManager, UserDataRepository); + + if (request.UserId.HasValue) + { + var user = UserManager.GetUserById(request.UserId.Value); + + return await builder.GetBaseItemDto(item, user, fields.ToList()).ConfigureAwait(false); + } + + return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false); + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> public object Get(GetYears request) { var result = GetResult(request).Result; @@ -51,9 +112,8 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <param name="items">The items.</param> - /// <param name="user">The user.</param> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> - protected override IEnumerable<IbnStub<Year>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items, User user) + protected override IEnumerable<IbnStub<Year>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) { var itemsList = items.Where(i => i.ProductionYear != null).ToList(); |
