new Artist entity
This commit is contained in:
parent
1a153cbd39
commit
374b7f2f03
|
@ -48,6 +48,19 @@ namespace MediaBrowser.Api.Images
|
|||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Artists/{Name}/Images/{Type}", "GET")]
|
||||
[Route("/Artists/{Name}/Images/{Type}/{Index}", "GET")]
|
||||
[Api(Description = "Gets an artist image")]
|
||||
public class GetArtistImage : ImageRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class GetStudioImage
|
||||
/// </summary>
|
||||
|
@ -233,6 +246,18 @@ namespace MediaBrowser.Api.Images
|
|||
return GetImage(request, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetArtistImage request)
|
||||
{
|
||||
var item = _libraryManager.GetArtist(request.Name).Result;
|
||||
|
||||
return GetImage(request, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
using MediaBrowser.Common;
|
||||
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;
|
||||
|
@ -36,66 +32,6 @@ namespace MediaBrowser.Api.Library
|
|||
public bool HasInternetProvider { get; set; }
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// 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>
|
||||
/// 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>
|
||||
/// 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>
|
||||
/// Class LibraryService
|
||||
/// </summary>
|
||||
|
@ -106,16 +42,14 @@ namespace MediaBrowser.Api.Library
|
|||
/// </summary>
|
||||
private readonly IApplicationHost _appHost;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
/// <exception cref="System.ArgumentNullException">appHost</exception>
|
||||
public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager)
|
||||
{
|
||||
if (appHost == null)
|
||||
{
|
||||
|
@ -124,75 +58,6 @@ namespace MediaBrowser.Api.Library
|
|||
|
||||
_appHost = appHost;
|
||||
_libraryManager = libraryManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetPerson request)
|
||||
{
|
||||
var item = _libraryManager.GetPerson(request.Name).Result;
|
||||
|
||||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetGenre request)
|
||||
{
|
||||
var item = _libraryManager.GetGenre(request.Name).Result;
|
||||
|
||||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetStudio request)
|
||||
{
|
||||
var item = _libraryManager.GetStudio(request.Name).Result;
|
||||
|
||||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetYear request)
|
||||
{
|
||||
var item = _libraryManager.GetYear(request.Year).Result;
|
||||
|
||||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
<Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" />
|
||||
<Compile Include="ApiEntryPoint.cs" />
|
||||
<Compile Include="SystemService.cs" />
|
||||
<Compile Include="UserLibrary\ArtistsService.cs" />
|
||||
<Compile Include="UserLibrary\BaseItemsByNameService.cs" />
|
||||
<Compile Include="UserLibrary\BaseItemsRequest.cs" />
|
||||
<Compile Include="UserLibrary\GenresService.cs" />
|
||||
|
|
187
MediaBrowser.Api/UserLibrary/ArtistsService.cs
Normal file
187
MediaBrowser.Api/UserLibrary/ArtistsService.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
@ -257,12 +289,24 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// </summary>
|
||||
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>
|
||||
|
|
|
@ -9,13 +9,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>
|
||||
|
|
|
@ -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
|
||||
|
@ -56,6 +75,80 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetGenre 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(GetGenre request)
|
||||
{
|
||||
var item = await LibraryManager.GetGenre(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(GetGenres 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<Genre>> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||
{
|
||||
var itemsList = items.Where(i => i.Genres != null).ToList();
|
||||
|
||||
return itemsList
|
||||
.SelectMany(i => i.Genres)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(name => new IbnStub<Genre>(name, () => itemsList.Where(i => i.Genres.Contains(name, StringComparer.OrdinalIgnoreCase)), GetEntity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entity.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{Genre}.</returns>
|
||||
protected Task<Genre> GetEntity(string name)
|
||||
{
|
||||
return LibraryManager.GetGenre(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
|
@ -63,9 +156,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetGenreItemCounts 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 items = GetItems(request.UserId).Where(i => i.Genres != null && i.Genres.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
var counts = new ItemByNameCounts
|
||||
{
|
||||
|
@ -86,44 +177,5 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
return ToOptimizedResult(counts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetGenres 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>
|
||||
/// <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)
|
||||
{
|
||||
var itemsList = items.Where(i => i.Genres != null).ToList();
|
||||
|
||||
return itemsList
|
||||
.SelectMany(i => i.Genres)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(name => new IbnStub<Genre>(name, () => itemsList.Where(i => i.Genres.Contains(name, StringComparer.OrdinalIgnoreCase)), GetEntity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entity.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{Genre}.</returns>
|
||||
protected Task<Genre> GetEntity(string name)
|
||||
{
|
||||
return LibraryManager.GetGenre(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,21 @@
|
|||
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;
|
||||
|
||||
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>
|
||||
|
@ -128,35 +126,32 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// </summary>
|
||||
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);
|
||||
|
||||
|
|
|
@ -21,6 +21,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
[Api(Description = "Gets items based on a query.")]
|
||||
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>
|
||||
|
@ -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 =>
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
|
@ -51,6 +52,28 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <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>
|
||||
|
@ -67,6 +90,42 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </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>
|
||||
|
@ -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(',');
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
|
@ -42,6 +43,28 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <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>
|
||||
|
@ -52,6 +75,42 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
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 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);
|
||||
}
|
||||
|
||||
return await builder.GetBaseItemDto(item, fields.ToList()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
|
@ -59,9 +118,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetStudioItemCounts request)
|
||||
{
|
||||
var user = UserManager.GetUserById(request.UserId);
|
||||
|
||||
var items = user.RootFolder.GetRecursiveChildren(user).Where(i => i.Studios != null && i.Studios.Contains(request.Name, StringComparer.OrdinalIgnoreCase)).ToList();
|
||||
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();
|
||||
|
||||
|
|
|
@ -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,13 +16,34 @@ 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>
|
||||
|
@ -34,6 +59,42 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </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>
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ namespace MediaBrowser.Controller.Dto
|
|||
recursiveItemCount++;
|
||||
|
||||
// Check is recently added
|
||||
if (child.IsRecentlyAdded(user))
|
||||
if (child.IsRecentlyAdded())
|
||||
{
|
||||
rcentlyAddedItemCount++;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
return "Artist-" + Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,5 +113,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
return (ProductionYear != null ? ProductionYear.Value.ToString("000-") : "")
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified name has artist.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns><c>true</c> if the specified name has artist; otherwise, <c>false</c>.</returns>
|
||||
public bool HasArtist(string name)
|
||||
{
|
||||
return Artists.Contains(name, StringComparer.OrdinalIgnoreCase) || string.Equals(AlbumArtist, name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
/// <summary>
|
||||
/// The unknwon artist
|
||||
/// </summary>
|
||||
private static readonly MusicArtist UnknwonArtist = new MusicArtist {Name = "<Unknown>"};
|
||||
private static readonly MusicArtist UnknwonArtist = new MusicArtist { Name = "<Unknown>" };
|
||||
|
||||
/// <summary>
|
||||
/// Override this to return the folder that should be used to construct a container
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -8,12 +6,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
/// </summary>
|
||||
public class MusicArtist : Folder
|
||||
{
|
||||
public Dictionary<string, string> AlbumCovers { get; set; }
|
||||
|
||||
public override void ClearMetaValues()
|
||||
{
|
||||
AlbumCovers = null;
|
||||
base.ClearMetaValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public abstract class BaseItem : IHasProviderIds
|
||||
{
|
||||
protected BaseItem()
|
||||
{
|
||||
Genres = new List<string>();
|
||||
TrailerUrls = new List<string>();
|
||||
Studios = new List<string>();
|
||||
People = new List<PersonInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The trailer folder name
|
||||
/// </summary>
|
||||
|
@ -925,16 +933,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <summary>
|
||||
/// Determines if the item is considered new based on user settings
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns><c>true</c> if [is recently added] [the specified user]; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public bool IsRecentlyAdded(User user)
|
||||
public bool IsRecentlyAdded()
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
return (DateTime.UtcNow - DateCreated).TotalDays < ConfigurationManager.Configuration.RecentItemDays;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
return "Genre-" + Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
return "Person-" + Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
return "Studio-" + Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
return "Year-" + Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,5 +213,13 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="parent">The parent.</param>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
IEnumerable<BaseItem> RetrieveChildren(Folder parent);
|
||||
|
||||
/// <summary>
|
||||
/// Validates the artists.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ValidateArtists(CancellationToken cancellationToken, IProgress<double> progress);
|
||||
}
|
||||
}
|
|
@ -53,8 +53,12 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="MoreLinq">
|
||||
<HintPath>..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
|
@ -111,9 +115,11 @@
|
|||
<Compile Include="Providers\IProviderManager.cs" />
|
||||
<Compile Include="Providers\MediaInfo\MediaEncoderHelpers.cs" />
|
||||
<Compile Include="Providers\MetadataProviderPriority.cs" />
|
||||
<Compile Include="Providers\Music\FanArtArtistByNameProvider.cs" />
|
||||
<Compile Include="Providers\Music\LastfmAlbumProvider.cs" />
|
||||
<Compile Include="Providers\Music\FanArtAlbumProvider.cs" />
|
||||
<Compile Include="Providers\Music\FanArtArtistProvider.cs" />
|
||||
<Compile Include="Providers\Music\LastfmArtistByNameProvider.cs" />
|
||||
<Compile Include="Providers\Music\LastfmArtistProvider.cs" />
|
||||
<Compile Include="Providers\Music\LastfmHelper.cs" />
|
||||
<Compile Include="Providers\Music\MusicArtistProviderFromJson.cs" />
|
||||
|
@ -197,6 +203,9 @@
|
|||
<Name>MediaBrowser.Model</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>if $(ConfigurationName) == Release (
|
||||
|
|
|
@ -14,11 +14,12 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <param name="item">The item.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="targetName">Name of the target.</param>
|
||||
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.String}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||
Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
|
||||
Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Saves to library filesystem.
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
Logger.Debug("FanArtProvider getting ClearLogo for " + movie.Name);
|
||||
try
|
||||
{
|
||||
movie.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(movie, path, LOGO_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
movie.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(movie, path, LOGO_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
Logger.Debug("FanArtProvider getting ClearArt for " + movie.Name);
|
||||
try
|
||||
{
|
||||
movie.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(movie, path, ART_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
movie.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(movie, path, ART_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -199,7 +199,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
Logger.Debug("FanArtProvider getting DiscArt for " + movie.Name);
|
||||
try
|
||||
{
|
||||
movie.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(movie, path, DISC_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
movie.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(movie, path, DISC_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -223,7 +223,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
Logger.Debug("FanArtProvider getting Banner for " + movie.Name);
|
||||
try
|
||||
{
|
||||
movie.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(movie, path, BANNER_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
movie.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(movie, path, BANNER_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -247,7 +247,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
Logger.Debug("FanArtProvider getting Banner for " + movie.Name);
|
||||
try
|
||||
{
|
||||
movie.SetImage(ImageType.Thumb, await _providerManager.DownloadAndSaveImage(movie, path, THUMB_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
movie.SetImage(ImageType.Thumb, await _providerManager.DownloadAndSaveImage(movie, path, THUMB_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
|
|
@ -251,7 +251,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
|
||||
};
|
||||
|
||||
public const string LOCAL_META_FILE_NAME = "MBMovie.json";
|
||||
public const string LOCAL_META_FILE_NAME = "mbmovie.js";
|
||||
public const string ALT_META_FILE_NAME = "movie.xml";
|
||||
protected string ItemType = "movie";
|
||||
|
||||
|
@ -268,7 +268,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
|
||||
}
|
||||
|
||||
if (providerInfo.LastRefreshStatus == ProviderRefreshStatus.CompletedWithErrors)
|
||||
if (providerInfo.LastRefreshStatus != ProviderRefreshStatus.Success)
|
||||
{
|
||||
Logger.Debug("MovieProvider for {0} - last attempt had errors. Will try again.", item.Path);
|
||||
return true;
|
||||
|
@ -281,9 +281,6 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
return false;
|
||||
}
|
||||
|
||||
if (DateTime.Today.Subtract(item.DateCreated).TotalDays > 180 && downloadDate != DateTime.MinValue)
|
||||
return false; // don't trigger a refresh data for item that are more than 6 months old and have been refreshed before
|
||||
|
||||
if (DateTime.Today.Subtract(downloadDate).TotalDays < ConfigurationManager.Configuration.MetadataRefreshDays) // only refresh every n days
|
||||
return false;
|
||||
|
||||
|
@ -1034,7 +1031,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
{
|
||||
try
|
||||
{
|
||||
item.PrimaryImagePath = await ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + poster.file_path, "folder" + Path.GetExtension(poster.file_path), MovieDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
item.PrimaryImagePath = await ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + poster.file_path, "folder" + Path.GetExtension(poster.file_path), ConfigurationManager.Configuration.SaveLocalMeta, MovieDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -1066,7 +1063,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
{
|
||||
try
|
||||
{
|
||||
item.BackdropImagePaths.Add(await ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + images.backdrops[i].file_path, bdName + Path.GetExtension(images.backdrops[i].file_path), MovieDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.BackdropImagePaths.Add(await ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + images.backdrops[i].file_path, bdName + Path.GetExtension(images.backdrops[i].file_path), ConfigurationManager.Configuration.SaveLocalMeta, MovieDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
/// <summary>
|
||||
/// The meta file name
|
||||
/// </summary>
|
||||
protected const string MetaFileName = "MBPerson.json";
|
||||
protected const string MetaFileName = "mbperson.js";
|
||||
|
||||
protected readonly IProviderManager ProviderManager;
|
||||
|
||||
|
|
|
@ -1,29 +1,34 @@
|
|||
using System.Collections.Generic;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Net;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.Music
|
||||
{
|
||||
public class FanArtAlbumProvider : FanartBaseProvider
|
||||
{
|
||||
private readonly IProviderManager _providerManager;
|
||||
|
||||
public FanArtAlbumProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
|
||||
|
||||
protected IHttpClient HttpClient { get; private set; }
|
||||
|
||||
public FanArtAlbumProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
|
||||
: base(logManager, configurationManager)
|
||||
{
|
||||
_providerManager = providerManager;
|
||||
HttpClient = httpClient;
|
||||
}
|
||||
|
||||
public override bool Supports(BaseItem item)
|
||||
{
|
||||
return item is MusicAlbum && item.Parent is MusicArtist;
|
||||
return item is MusicAlbum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -35,7 +40,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
|
||||
{
|
||||
//we fetch if image needed and haven't already tried recently
|
||||
return string.IsNullOrEmpty(item.PrimaryImagePath) &&
|
||||
return (string.IsNullOrEmpty(item.PrimaryImagePath) || !item.HasImage(ImageType.Disc)) &&
|
||||
DateTime.Today.Subtract(providerInfo.LastRefreshed).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays;
|
||||
}
|
||||
|
||||
|
@ -45,46 +50,81 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
if (mbid == null)
|
||||
{
|
||||
Logger.Warn("No Musicbrainz id associated with album {0}", item.Name);
|
||||
SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.CompletedWithErrors);
|
||||
return false;
|
||||
SetLastRefreshed(item, DateTime.UtcNow);
|
||||
return true;
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
//Look at our parent for our album cover
|
||||
var artist = (MusicArtist)item.Parent;
|
||||
var url = string.Format("http://api.fanart.tv/webservice/album/{0}/{1}/xml/all/1/1", APIKey, item.GetProviderId(MetadataProviders.Musicbrainz));
|
||||
|
||||
var cover = artist.AlbumCovers != null ? GetValueOrDefault(artist.AlbumCovers, mbid, null) : null;
|
||||
var doc = new XmlDocument();
|
||||
|
||||
if (cover == null)
|
||||
try
|
||||
{
|
||||
using (var xml = await HttpClient.Get(url, FanArtResourcePool, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
doc.Load(xml);
|
||||
}
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
Logger.Warn("Unable to find cover art for {0}", item.Name);
|
||||
SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.CompletedWithErrors);
|
||||
return false;
|
||||
}
|
||||
|
||||
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, cover, "folder.jpg", FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (doc.HasChildNodes)
|
||||
{
|
||||
if (ConfigurationManager.Configuration.DownloadMusicAlbumImages.Disc && !item.ResolveArgs.ContainsMetaFileByName(DISC_FILE))
|
||||
{
|
||||
var node = doc.SelectSingleNode("//fanart/music/albums/album//cdart/@url");
|
||||
|
||||
var path = node != null ? node.Value : null;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting Disc for " + item.Name);
|
||||
try
|
||||
{
|
||||
item.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(item, path, DISC_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigurationManager.Configuration.DownloadMusicAlbumImages.Primary && !item.ResolveArgs.ContainsMetaFileByName(PRIMARY_FILE))
|
||||
{
|
||||
var node = doc.SelectSingleNode("//fanart/music/albums/album//albumcover/@url");
|
||||
|
||||
var path = node != null ? node.Value : null;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting albumcover for " + item.Name);
|
||||
try
|
||||
{
|
||||
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, path, PRIMARY_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetLastRefreshed(item, DateTime.UtcNow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Dictionaries since they throw on not-found keys
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="U"></typeparam>
|
||||
/// <param name="dictionary">The dictionary.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>``1.</returns>
|
||||
private static U GetValueOrDefault<T, U>(Dictionary<T, U> dictionary, T key, U defaultValue)
|
||||
{
|
||||
U val;
|
||||
if (!dictionary.TryGetValue(key, out val))
|
||||
{
|
||||
val = defaultValue;
|
||||
}
|
||||
return val;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.Music
|
||||
{
|
||||
/// <summary>
|
||||
/// Class FanArtArtistByNameProvider
|
||||
/// </summary>
|
||||
public class FanArtArtistByNameProvider : FanArtArtistProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FanArtArtistByNameProvider" /> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClient">The HTTP client.</param>
|
||||
/// <param name="logManager">The log manager.</param>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
/// <param name="providerManager">The provider manager.</param>
|
||||
public FanArtArtistByNameProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
|
||||
: base(httpClient, logManager, configurationManager, providerManager)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
public override bool Supports(BaseItem item)
|
||||
{
|
||||
return item is Artist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [save local meta].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
|
||||
protected override bool SaveLocalMeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
/// <summary>
|
||||
/// Class FanArtArtistProvider
|
||||
/// </summary>
|
||||
class FanArtArtistProvider : FanartBaseProvider
|
||||
public class FanArtArtistProvider : FanartBaseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the HTTP client.
|
||||
|
@ -54,6 +54,11 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
return item is MusicArtist;
|
||||
}
|
||||
|
||||
protected virtual bool SaveLocalMeta
|
||||
{
|
||||
get { return ConfigurationManager.Configuration.SaveLocalMeta; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shoulds the fetch.
|
||||
/// </summary>
|
||||
|
@ -62,16 +67,11 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
protected override bool ShouldFetch(BaseItem item, BaseProviderInfo providerInfo)
|
||||
{
|
||||
var artist = (MusicArtist)item;
|
||||
if (item.Path == null || item.DontFetchMeta || string.IsNullOrEmpty(artist.GetProviderId(MetadataProviders.Musicbrainz))) return false; //nothing to do
|
||||
var artExists = item.ResolveArgs.ContainsMetaFileByName(ART_FILE);
|
||||
var logoExists = item.ResolveArgs.ContainsMetaFileByName(LOGO_FILE);
|
||||
var discExists = item.ResolveArgs.ContainsMetaFileByName(DISC_FILE);
|
||||
if (item.Path == null || item.DontFetchMeta || string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz))) return false; //nothing to do
|
||||
|
||||
return (!artExists && ConfigurationManager.Configuration.DownloadMusicArtistImages.Art)
|
||||
|| (!logoExists && ConfigurationManager.Configuration.DownloadMusicArtistImages.Logo)
|
||||
|| (!discExists && ConfigurationManager.Configuration.DownloadMusicArtistImages.Disc)
|
||||
|| ((artist.AlbumCovers == null || artist.AlbumCovers.Count == 0) && ConfigurationManager.Configuration.DownloadMusicAlbumImages.Primary);
|
||||
return (!item.ResolveArgs.ContainsMetaFileByName(ART_FILE) && ConfigurationManager.Configuration.DownloadMusicArtistImages.Art)
|
||||
|| (!item.ResolveArgs.ContainsMetaFileByName(LOGO_FILE) && ConfigurationManager.Configuration.DownloadMusicArtistImages.Logo)
|
||||
|| (!item.ResolveArgs.ContainsMetaFileByName(DISC_FILE) && ConfigurationManager.Configuration.DownloadMusicArtistImages.Disc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -85,7 +85,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var artist = (MusicArtist)item;
|
||||
//var artist = item;
|
||||
|
||||
BaseProviderInfo providerData;
|
||||
|
||||
|
@ -94,9 +94,9 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
providerData = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
if (ShouldFetch(artist, providerData))
|
||||
if (ShouldFetch(item, providerData))
|
||||
{
|
||||
var url = string.Format(FanArtBaseUrl, APIKey, artist.GetProviderId(MetadataProviders.Musicbrainz));
|
||||
var url = string.Format(FanArtBaseUrl, APIKey, item.GetProviderId(MetadataProviders.Musicbrainz));
|
||||
var doc = new XmlDocument();
|
||||
|
||||
try
|
||||
|
@ -124,10 +124,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
path = node != null ? node.Value : null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting ClearLogo for " + artist.Name);
|
||||
Logger.Debug("FanArtProvider getting ClearLogo for " + item.Name);
|
||||
try
|
||||
{
|
||||
artist.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(artist, path, LOGO_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(item, path, LOGO_FILE, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -146,16 +146,16 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
if (nodes != null)
|
||||
{
|
||||
var numBackdrops = 0;
|
||||
artist.BackdropImagePaths = new List<string>();
|
||||
item.BackdropImagePaths = new List<string>();
|
||||
foreach (XmlNode node in nodes)
|
||||
{
|
||||
path = node.Value;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting Backdrop for " + artist.Name);
|
||||
Logger.Debug("FanArtProvider getting Backdrop for " + item.Name);
|
||||
try
|
||||
{
|
||||
artist.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(artist, path, ("Backdrop" + (numBackdrops > 0 ? numBackdrops.ToString() : "") + ".jpg"), FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(item, path, ("Backdrop" + (numBackdrops > 0 ? numBackdrops.ToString() : "") + ".jpg"), SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
numBackdrops++;
|
||||
if (numBackdrops >= ConfigurationManager.Configuration.MaxBackdrops) break;
|
||||
}
|
||||
|
@ -175,32 +175,6 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (ConfigurationManager.Configuration.DownloadMusicAlbumImages.Primary)
|
||||
{
|
||||
var nodes = doc.SelectNodes("//fanart/music/albums/*");
|
||||
if (nodes != null)
|
||||
{
|
||||
artist.AlbumCovers = new Dictionary<string, string>();
|
||||
foreach (XmlNode node in nodes)
|
||||
{
|
||||
|
||||
var key = node.Attributes["id"] != null ? node.Attributes["id"].Value : null;
|
||||
var cover = node.SelectSingleNode("albumcover/@url");
|
||||
path = cover != null ? cover.Value : null;
|
||||
|
||||
if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(key))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting Album Cover for " + artist.Name);
|
||||
artist.AlbumCovers[key] = path;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (ConfigurationManager.Configuration.DownloadMusicArtistImages.Art && !item.ResolveArgs.ContainsMetaFileByName(ART_FILE))
|
||||
{
|
||||
var node =
|
||||
|
@ -209,10 +183,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
path = node != null ? node.Value : null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting ClearArt for " + artist.Name);
|
||||
Logger.Debug("FanArtProvider getting ClearArt for " + item.Name);
|
||||
try
|
||||
{
|
||||
artist.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(artist, path, ART_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(item, path, ART_FILE, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -232,10 +206,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
path = node != null ? node.Value : null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting Banner for " + artist.Name);
|
||||
Logger.Debug("FanArtProvider getting Banner for " + item.Name);
|
||||
try
|
||||
{
|
||||
artist.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(artist, path, BANNER_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(item, path, BANNER_FILE, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -256,10 +230,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
path = node != null ? node.Value : null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
Logger.Debug("FanArtProvider getting Primary image for " + artist.Name);
|
||||
Logger.Debug("FanArtProvider getting Primary image for " + item.Name);
|
||||
try
|
||||
{
|
||||
artist.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(artist, path, PRIMARY_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, path, PRIMARY_FILE, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -272,7 +246,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
}
|
||||
}
|
||||
}
|
||||
SetLastRefreshed(artist, DateTime.UtcNow);
|
||||
SetLastRefreshed(item, DateTime.UtcNow);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MoreLinq;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.Music
|
||||
{
|
||||
|
@ -33,26 +34,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
|
||||
protected override async Task FetchLastfmData(BaseItem item, string id, CancellationToken cancellationToken)
|
||||
{
|
||||
// Get albu info using artist and album name
|
||||
var url = RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(item.Parent.Name), UrlEncode(item.Name), ApiKey);
|
||||
|
||||
LastfmGetAlbumResult result;
|
||||
|
||||
try
|
||||
{
|
||||
using (var json = await HttpClient.Get(url, LastfmResourcePool, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
result = JsonSerializer.DeserializeFromStream<LastfmGetAlbumResult>(json);
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
if (e.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
throw new LastfmProviderException(string.Format("Unable to retrieve album info for {0} with artist {1}", item.Name, item.Parent.Name));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
var result = await GetAlbumResult(item, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (result != null && result.album != null)
|
||||
{
|
||||
|
@ -71,9 +53,60 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<LastfmGetAlbumResult> GetAlbumResult(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await GetAlbumResult(item.Parent.Name, item.Name, cancellationToken);
|
||||
|
||||
if (result != null && result.album != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var folder = (Folder)item;
|
||||
|
||||
// Get each song, distinct by the combination of AlbumArtist and Album
|
||||
var songs = folder.Children.OfType<Audio>().DistinctBy(i => (i.AlbumArtist ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
foreach (var song in songs.Where(song => !string.IsNullOrEmpty(song.Album) && !string.IsNullOrEmpty(song.AlbumArtist)))
|
||||
{
|
||||
result = await GetAlbumResult(song.AlbumArtist, song.Album, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (result != null && result.album != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<LastfmGetAlbumResult> GetAlbumResult(string artist, string album, CancellationToken cancellationToken)
|
||||
{
|
||||
// Get albu info using artist and album name
|
||||
var url = RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(artist), UrlEncode(album), ApiKey);
|
||||
|
||||
using (var json = await HttpClient.Get(url, LastfmResourcePool, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return JsonSerializer.DeserializeFromStream<LastfmGetAlbumResult>(json);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Task FetchData(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
return FetchLastfmData(item, string.Empty, cancellationToken);
|
||||
}
|
||||
|
||||
public override bool Supports(BaseItem item)
|
||||
{
|
||||
return item is MusicAlbum;
|
||||
}
|
||||
|
||||
protected override bool RefreshOnFileSystemStampChange
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.Music
|
||||
{
|
||||
/// <summary>
|
||||
/// Class LastfmArtistByNameProvider
|
||||
/// </summary>
|
||||
public class LastfmArtistByNameProvider : LastfmArtistProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LastfmArtistByNameProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="jsonSerializer">The json serializer.</param>
|
||||
/// <param name="httpClient">The HTTP client.</param>
|
||||
/// <param name="logManager">The log manager.</param>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
/// <param name="providerManager">The provider manager.</param>
|
||||
public LastfmArtistByNameProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
|
||||
: base(jsonSerializer, httpClient, logManager, configurationManager, providerManager)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [save local meta].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
|
||||
protected override bool SaveLocalMeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
public override bool Supports(BaseItem item)
|
||||
{
|
||||
return item is Artist;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
//Execute the Artist search against our name and assume first one is the one we want
|
||||
var url = RootUrl + string.Format("method=artist.search&artist={0}&api_key={1}&format=json", UrlEncode(item.Name), ApiKey);
|
||||
|
||||
LastfmArtistSearchResults searchResult = null;
|
||||
LastfmArtistSearchResults searchResult;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -60,29 +60,18 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
// Get artist info with provided id
|
||||
var url = RootUrl + string.Format("method=artist.getInfo&mbid={0}&api_key={1}&format=json", UrlEncode(id), ApiKey);
|
||||
|
||||
LastfmGetArtistResult result = null;
|
||||
LastfmGetArtistResult result;
|
||||
|
||||
try
|
||||
using (var json = await HttpClient.Get(url, LastfmResourcePool, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
using (var json = await HttpClient.Get(url, LastfmResourcePool, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
result = JsonSerializer.DeserializeFromStream<LastfmGetArtistResult>(json);
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
if (e.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
throw new LastfmProviderException(string.Format("Unable to retrieve artist info for {0} with id {1}", item.Name, id));
|
||||
}
|
||||
throw;
|
||||
result = JsonSerializer.DeserializeFromStream<LastfmGetArtistResult>(json);
|
||||
}
|
||||
|
||||
if (result != null && result.artist != null)
|
||||
{
|
||||
LastfmHelper.ProcessArtistData(item, result.artist);
|
||||
//And save locally if indicated
|
||||
if (ConfigurationManager.Configuration.SaveLocalMeta)
|
||||
if (SaveLocalMeta)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
JsonSerializer.SerializeToStream(result.artist, ms);
|
||||
|
|
|
@ -1,26 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers.Music
|
||||
{
|
||||
class LastfmProviderException : ApplicationException
|
||||
{
|
||||
public LastfmProviderException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Class MovieDbProvider
|
||||
/// </summary>
|
||||
|
@ -84,6 +75,14 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
/// </summary>
|
||||
protected string LocalMetaFileName { get; set; }
|
||||
|
||||
protected virtual bool SaveLocalMeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.Configuration.SaveLocalMeta;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If we save locally, refresh if they delete something
|
||||
/// </summary>
|
||||
|
@ -91,7 +90,7 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
{
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.Configuration.SaveLocalMeta;
|
||||
return SaveLocalMeta;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,16 +172,15 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
{
|
||||
if (item.DontFetchMeta) return false;
|
||||
|
||||
if (ConfigurationManager.Configuration.SaveLocalMeta && HasFileSystemStampChanged(item, providerInfo))
|
||||
if (RefreshOnFileSystemStampChange && HasFileSystemStampChanged(item, providerInfo))
|
||||
{
|
||||
//If they deleted something from file system, chances are, this item was mis-identified the first time
|
||||
item.SetProviderId(MetadataProviders.Musicbrainz, null);
|
||||
Logger.Debug("LastfmProvider reports file system stamp change...");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (providerInfo.LastRefreshStatus == ProviderRefreshStatus.CompletedWithErrors)
|
||||
if (providerInfo.LastRefreshStatus != ProviderRefreshStatus.Success)
|
||||
{
|
||||
Logger.Debug("LastfmProvider for {0} - last attempt had errors. Will try again.", item.Path);
|
||||
return true;
|
||||
|
@ -194,22 +192,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
return true;
|
||||
}
|
||||
|
||||
var downloadDate = providerInfo.LastRefreshed;
|
||||
if (DateTime.UtcNow.Subtract(providerInfo.LastRefreshed).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays) // only refresh every n days
|
||||
return true;
|
||||
|
||||
if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DateTime.Today.Subtract(item.DateCreated).TotalDays > 180 && downloadDate != DateTime.MinValue)
|
||||
return false; // don't trigger a refresh data for item that are more than 6 months old and have been refreshed before
|
||||
|
||||
if (DateTime.Today.Subtract(downloadDate).TotalDays < ConfigurationManager.Configuration.MetadataRefreshDays) // only refresh every n days
|
||||
return false;
|
||||
|
||||
|
||||
Logger.Debug("LastfmProvider - " + item.Name + " needs refresh. Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + ConfigurationManager.Configuration.MetadataRefreshDays);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -221,36 +207,9 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
/// <returns>Task{System.Boolean}.</returns>
|
||||
public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
|
||||
{
|
||||
if (item.DontFetchMeta)
|
||||
{
|
||||
Logger.Info("LastfmProvider - Not fetching because requested to ignore " + item.Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
BaseProviderInfo providerData;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(Id, out providerData))
|
||||
{
|
||||
providerData = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
if (!ConfigurationManager.Configuration.SaveLocalMeta || !HasLocalMeta(item) || (force && !HasLocalMeta(item)) || (RefreshOnVersionChange && providerData.ProviderVersion != ProviderVersion))
|
||||
{
|
||||
try
|
||||
{
|
||||
await FetchData(item, cancellationToken).ConfigureAwait(false);
|
||||
SetLastRefreshed(item, DateTime.UtcNow);
|
||||
}
|
||||
catch (LastfmProviderException)
|
||||
{
|
||||
SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.CompletedWithErrors);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Logger.Debug("LastfmProvider not fetching because local meta exists for " + item.Name);
|
||||
await FetchData(item, cancellationToken).ConfigureAwait(false);
|
||||
SetLastRefreshed(item, DateTime.UtcNow);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,20 +6,23 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
{
|
||||
public static class LastfmHelper
|
||||
{
|
||||
public static string LocalArtistMetaFileName = "MBArtist.json";
|
||||
public static string LocalAlbumMetaFileName = "MBAlbum.json";
|
||||
public static string LocalArtistMetaFileName = "mbartist.js";
|
||||
public static string LocalAlbumMetaFileName = "mbalbum.js";
|
||||
|
||||
public static void ProcessArtistData(BaseItem artist, LastfmArtist data)
|
||||
{
|
||||
var overview = data.bio != null ? data.bio.content : null;
|
||||
|
||||
artist.Overview = overview;
|
||||
|
||||
var yearFormed = 0;
|
||||
|
||||
if (data.bio != null)
|
||||
{
|
||||
Int32.TryParse(data.bio.yearformed, out yearFormed);
|
||||
|
||||
artist.Overview = data.bio.content;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.bio.placeformed))
|
||||
{
|
||||
artist.AddProductionLocation(data.bio.placeformed);
|
||||
}
|
||||
}
|
||||
|
||||
artist.PremiereDate = yearFormed > 0 ? new DateTime(yearFormed, 1,1) : DateTime.MinValue;
|
||||
|
@ -52,7 +55,10 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
{
|
||||
foreach (var tag in tags.tag)
|
||||
{
|
||||
item.AddGenre(tag.name);
|
||||
if (!string.IsNullOrEmpty(tag.name))
|
||||
{
|
||||
item.AddGenre(tag.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
Logger.Debug("FanArtProvider getting ClearLogo for " + series.Name);
|
||||
try
|
||||
{
|
||||
series.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(series, path, LOGO_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
series.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(series, path, LOGO_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
Logger.Debug("FanArtProvider getting ClearArt for " + series.Name);
|
||||
try
|
||||
{
|
||||
series.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(series, path, ART_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
series.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(series, path, ART_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -148,7 +148,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
Logger.Debug("FanArtProvider getting ThumbArt for " + series.Name);
|
||||
try
|
||||
{
|
||||
series.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(series, path, THUMB_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
series.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(series, path, THUMB_FILE, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
|
||||
try
|
||||
{
|
||||
episode.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
|
||||
episode.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
try
|
||||
{
|
||||
if (n != null)
|
||||
season.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
season.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -204,7 +204,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
TVUtils.BannerUrl + n.InnerText,
|
||||
"banner" +
|
||||
Path.GetExtension(n.InnerText),
|
||||
RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).
|
||||
ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).
|
||||
ConfigureAwait(false);
|
||||
|
||||
season.SetImage(ImageType.Banner, bannerImagePath);
|
||||
|
@ -231,7 +231,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
try
|
||||
{
|
||||
if (season.BackdropImagePaths == null) season.BackdropImagePaths = new List<string>();
|
||||
season.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
season.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -265,7 +265,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
"backdrop" +
|
||||
Path.GetExtension(
|
||||
n.InnerText),
|
||||
RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken)
|
||||
ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken)
|
||||
.ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
|
|
|
@ -228,7 +228,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
string n = doc.SafeGetString("//banner");
|
||||
if (!string.IsNullOrWhiteSpace(n))
|
||||
{
|
||||
series.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n, "banner" + Path.GetExtension(n), TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
series.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n, "banner" + Path.GetExtension(n), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
string s = doc.SafeGetString("//Network");
|
||||
|
@ -369,7 +369,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
{
|
||||
try
|
||||
{
|
||||
series.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), TvDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
series.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -392,7 +392,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
{
|
||||
try
|
||||
{
|
||||
var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), TvDbResourcePool, cancellationToken);
|
||||
var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken);
|
||||
|
||||
series.SetImage(ImageType.Banner, bannerImagePath);
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
{
|
||||
try
|
||||
{
|
||||
series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
|
4
MediaBrowser.Controller/packages.config
Normal file
4
MediaBrowser.Controller/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="morelinq" version="1.0.15631-beta" targetFramework="net45" />
|
||||
</packages>
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Common.Events;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Progress;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
@ -103,7 +104,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration manager.
|
||||
/// </summary>
|
||||
|
@ -244,7 +245,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
// Any number of configuration settings could change the way the library is refreshed, so do that now
|
||||
_taskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>();
|
||||
|
||||
|
||||
if (refreshPeopleAfterUpdate)
|
||||
{
|
||||
_taskManager.CancelIfRunningAndQueue<PeopleValidationTask>();
|
||||
|
@ -285,7 +286,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
items.AddRange(userFolders);
|
||||
|
||||
return new ConcurrentDictionary<Guid,BaseItem>(items.ToDictionary(i => i.Id));
|
||||
return new ConcurrentDictionary<Guid, BaseItem>(items.ToDictionary(i => i.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -505,7 +506,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
return _userRootFolders.GetOrAdd(userRootPath, key => RetrieveItem(userRootPath.GetMBId(typeof(UserRootFolder))) as UserRootFolder ?? (UserRootFolder)ResolvePath(userRootPath));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Person
|
||||
/// </summary>
|
||||
|
@ -560,7 +561,20 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
/// <returns>Task{Genre}.</returns>
|
||||
public Task<Artist> GetArtist(string name, bool allowSlowProviders = false)
|
||||
{
|
||||
return GetImagesByNameItem<Artist>(ConfigurationManager.ApplicationPaths.ArtistsPath, name, CancellationToken.None, allowSlowProviders);
|
||||
return GetArtist(name, CancellationToken.None, allowSlowProviders);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the artist.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
|
||||
/// <param name="forceCreation">if set to <c>true</c> [force creation].</param>
|
||||
/// <returns>Task{Artist}.</returns>
|
||||
private Task<Artist> GetArtist(string name, CancellationToken cancellationToken, bool allowSlowProviders = false, bool forceCreation = false)
|
||||
{
|
||||
return GetImagesByNameItem<Artist>(ConfigurationManager.ApplicationPaths.ArtistsPath, name, cancellationToken, allowSlowProviders, forceCreation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -764,6 +778,76 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
_logger.Info("People validation complete");
|
||||
}
|
||||
|
||||
public async Task ValidateArtists(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
const int maxTasks = 25;
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
var artists = RootFolder.RecursiveChildren
|
||||
.OfType<Audio>()
|
||||
.SelectMany(c =>
|
||||
{
|
||||
var list = c.Artists.ToList();
|
||||
|
||||
if (!string.IsNullOrEmpty(c.AlbumArtist))
|
||||
{
|
||||
list.Add(c.AlbumArtist);
|
||||
}
|
||||
|
||||
return list;
|
||||
})
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
var numComplete = 0;
|
||||
|
||||
foreach (var artist in artists)
|
||||
{
|
||||
if (tasks.Count > maxTasks)
|
||||
{
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
tasks.Clear();
|
||||
|
||||
// Safe cancellation point, when there are no pending tasks
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
// Avoid accessing the foreach variable within the closure
|
||||
var currentArtist = artist;
|
||||
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
await GetArtist(currentArtist, cancellationToken, true, true).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.ErrorException("Error validating Artist {0}", ex, currentArtist);
|
||||
}
|
||||
|
||||
// Update progress
|
||||
lock (progress)
|
||||
{
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
percent /= artists.Count;
|
||||
|
||||
progress.Report(100 * percent);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
progress.Report(100);
|
||||
|
||||
_logger.Info("Artist validation complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads the root media folder
|
||||
/// </summary>
|
||||
|
@ -796,8 +880,20 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
await ValidateCollectionFolders(folder, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
|
||||
innerProgress.RegisterAction(pct => progress.Report(pct * .8));
|
||||
|
||||
// Now validate the entire media library
|
||||
await RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
|
||||
await RootFolder.ValidateChildren(innerProgress, cancellationToken, recursive: true).ConfigureAwait(false);
|
||||
|
||||
innerProgress = new ActionableProgress<double>();
|
||||
|
||||
innerProgress.RegisterAction(pct => progress.Report(80 + pct * .2));
|
||||
|
||||
await ValidateArtists(cancellationToken, innerProgress);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -145,6 +145,7 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Providers\ProviderManager.cs" />
|
||||
<Compile Include="Reflection\TypeMapper.cs" />
|
||||
<Compile Include="ScheduledTasks\ArtistValidationTask.cs" />
|
||||
<Compile Include="ScheduledTasks\PeopleValidationTask.cs" />
|
||||
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
|
||||
<Compile Include="ScheduledTasks\ImageCleanupTask.cs" />
|
||||
|
|
|
@ -330,11 +330,12 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
/// <param name="item">The item.</param>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="targetName">Name of the target.</param>
|
||||
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
|
||||
/// <param name="resourcePool">The resource pool.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.String}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||
public async Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
public async Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
|
@ -354,13 +355,13 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
}
|
||||
|
||||
//download and save locally
|
||||
var localPath = (ConfigurationManager.Configuration.SaveLocalMeta && item.MetaLocation != null) ?
|
||||
var localPath = (saveLocally && item.MetaLocation != null) ?
|
||||
Path.Combine(item.MetaLocation, targetName) :
|
||||
_remoteImageCache.GetResourcePath(item.GetType().FullName + item.Path.ToLower(), targetName);
|
||||
|
||||
var img = await _httpClient.Get(source, resourcePool, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (ConfigurationManager.Configuration.SaveLocalMeta) // queue to media directories
|
||||
if (saveLocally) // queue to media directories
|
||||
{
|
||||
await SaveToLibraryFilesystem(item, localPath, img, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
public class ArtistValidationTask
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public ArtistValidationTask(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
||||
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
||||
{
|
||||
return new ITaskTrigger[]
|
||||
{
|
||||
new DailyTrigger { TimeOfDay = TimeSpan.FromHours(5) },
|
||||
|
||||
new IntervalTrigger{ Interval = TimeSpan.FromHours(12)}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the task to be executed
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
return _libraryManager.ValidateArtists(cancellationToken, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the task
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name
|
||||
{
|
||||
get { return "Refresh music artists"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
/// <value>The description.</value>
|
||||
public string Description
|
||||
{
|
||||
get { return "Updates metadata for music artists in your media library."; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the category.
|
||||
/// </summary>
|
||||
/// <value>The category.</value>
|
||||
public string Category
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Library";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
|
|||
/// <value>The description.</value>
|
||||
public string Description
|
||||
{
|
||||
get { return "Updates metadata for actors, artists and directors in your media library."; }
|
||||
get { return "Updates metadata for actors and directors in your media library."; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -150,6 +150,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private readonly object _disposeLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
|
@ -160,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
lock (_disposeLock)
|
||||
{
|
||||
if (connection != null)
|
||||
{
|
||||
|
|
|
@ -477,6 +477,8 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
"moviesrecommended.js",
|
||||
"moviestudios.js",
|
||||
"movietrailers.js",
|
||||
"musicalbums.js",
|
||||
"musicartists.js",
|
||||
"musicgenres.js",
|
||||
"playlist.js",
|
||||
"plugincatalogpage.js",
|
||||
|
|
|
@ -862,13 +862,19 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
/**
|
||||
* Gets a studio
|
||||
*/
|
||||
self.getStudio = function (name) {
|
||||
self.getStudio = function (name, userId) {
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Studios/" + encodeName(name));
|
||||
var options = {};
|
||||
|
||||
if (userId) {
|
||||
options.userId = userId;
|
||||
}
|
||||
|
||||
var url = self.getUrl("Studios/" + encodeName(name), options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -880,13 +886,43 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
/**
|
||||
* Gets a genre
|
||||
*/
|
||||
self.getGenre = function (name) {
|
||||
self.getGenre = function (name, userId) {
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Genres/" + encodeName(name));
|
||||
var options = {};
|
||||
|
||||
if (userId) {
|
||||
options.userId = userId;
|
||||
}
|
||||
|
||||
var url = self.getUrl("Genres/" + encodeName(name), options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json"
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets an artist
|
||||
*/
|
||||
self.getArtist = function (name, userId) {
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var options = {};
|
||||
|
||||
if (userId) {
|
||||
options.userId = userId;
|
||||
}
|
||||
|
||||
var url = self.getUrl("Artists/" + encodeName(name), options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -898,13 +934,19 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
/**
|
||||
* Gets a year
|
||||
*/
|
||||
self.getYear = function (year) {
|
||||
self.getYear = function (yea, userId) {
|
||||
|
||||
if (!year) {
|
||||
throw new Error("null year");
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Years/" + year);
|
||||
var options = {};
|
||||
|
||||
if (userId) {
|
||||
options.userId = userId;
|
||||
}
|
||||
|
||||
var url = self.getUrl("Years/" + encodeName(name), options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -916,13 +958,19 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
/**
|
||||
* Gets a Person
|
||||
*/
|
||||
self.getPerson = function (name) {
|
||||
self.getPerson = function (name, userId) {
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Persons/" + encodeName(name));
|
||||
var options = {};
|
||||
|
||||
if (userId) {
|
||||
options.userId = userId;
|
||||
}
|
||||
|
||||
var url = self.getUrl("Persons/" + encodeName(name), options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1131,6 +1179,41 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
return self.getUrl(url, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a url for a artist 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.getArtistImageUrl = function (name, options) {
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
options = options || {
|
||||
|
||||
};
|
||||
|
||||
var url = "Artists/" + encodeName(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 studio image
|
||||
* @param {String} name
|
||||
|
@ -1524,6 +1607,27 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
Gets artists from an item
|
||||
*/
|
||||
self.getArtists = function (userId, options) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.userId = userId;
|
||||
|
||||
var url = self.getUrl("Artists", options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json"
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
Gets genres from an item
|
||||
*/
|
||||
|
@ -1533,12 +1637,10 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
var parentId = options.parentId || "root";
|
||||
options = options || {};
|
||||
options.userId = userId;
|
||||
|
||||
// Don't put these on the query string
|
||||
delete options.parentId;
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Items/" + parentId + "/Genres", options);
|
||||
var url = self.getUrl("Genres", options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1556,12 +1658,10 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
var parentId = options.parentId || "root";
|
||||
options = options || {};
|
||||
options.userId = userId;
|
||||
|
||||
// Don't put these on the query string
|
||||
delete options.parentId;
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Items/" + parentId + "/Persons", options);
|
||||
var url = self.getUrl("Persons", options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1579,12 +1679,10 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
var parentId = options.parentId || "root";
|
||||
options = options || {};
|
||||
options.userId = userId;
|
||||
|
||||
// Don't put these on the query string
|
||||
delete options.parentId;
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Items/" + parentId + "/Studios", options);
|
||||
var url = self.getUrl("Studios", options);
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1722,7 +1820,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
* @param {String} name
|
||||
* @param {Boolean} isFavorite
|
||||
*/
|
||||
self.updateItemByNameFavoriteStatus = function (userId, name, isFavorite) {
|
||||
self.updateFavoriteArtistStatus = function (userId, name, isFavorite) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
|
@ -1732,7 +1830,67 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/ItemsByName/Favorites/" + encodeName(name));
|
||||
var url = self.getUrl("Users/" + userId + "/Favorites/Artists/" + encodeName(name));
|
||||
|
||||
var method = isFavorite ? "POST" : "DELETE";
|
||||
|
||||
return self.ajax({
|
||||
type: method,
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updateFavoritePersonStatus = function (userId, name, isFavorite) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Favorites/Persons/" + encodeName(name));
|
||||
|
||||
var method = isFavorite ? "POST" : "DELETE";
|
||||
|
||||
return self.ajax({
|
||||
type: method,
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updateFavoriteStudioStatus = function (userId, name, isFavorite) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Favorites/Studios/" + encodeName(name));
|
||||
|
||||
var method = isFavorite ? "POST" : "DELETE";
|
||||
|
||||
return self.ajax({
|
||||
type: method,
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updateFavoriteGenreStatus = function (userId, name, isFavorite) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Favorites/Genres/" + encodeName(name));
|
||||
|
||||
var method = isFavorite ? "POST" : "DELETE";
|
||||
|
||||
|
@ -1748,7 +1906,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
* @param {String} name
|
||||
* @param {Boolean} likes
|
||||
*/
|
||||
self.updateItemByNameRating = function (userId, name, likes) {
|
||||
self.updateArtistRating = function (userId, name, likes) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
|
@ -1758,7 +1916,67 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/ItemsByName/" + encodeName(name) + "/Rating", {
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Artists/" + encodeName(name), {
|
||||
likes: likes
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "POST",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updatePersonRating = function (userId, name, likes) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Persons/" + encodeName(name), {
|
||||
likes: likes
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "POST",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updateStudioRating = function (userId, name, likes) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Studios/" + encodeName(name), {
|
||||
likes: likes
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "POST",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.updateGenreRating = function (userId, name, likes) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Genres/" + encodeName(name), {
|
||||
likes: likes
|
||||
});
|
||||
|
||||
|
@ -1773,7 +1991,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
* @param {String} userId
|
||||
* @param {String} name
|
||||
*/
|
||||
self.clearItemByNameRating = function (userId, name) {
|
||||
self.clearArtistRating = function (userId, name) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
|
@ -1783,7 +2001,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/ItemsByName/" + encodeName(name) + "/Rating");
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Artists/" + encodeName(name));
|
||||
|
||||
return self.ajax({
|
||||
type: "DELETE",
|
||||
|
@ -1791,12 +2009,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the full user data object for an item by name.
|
||||
* @param {String} userId
|
||||
* @param {String} name
|
||||
*/
|
||||
self.getItembyNameUserData = function (userId, name) {
|
||||
self.clearPersonRating = function (userId, name) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
|
@ -1806,12 +2019,47 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/ItemsByName/" + encodeName(name) + "/UserData");
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Persons/" + encodeName(name));
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json"
|
||||
type: "DELETE",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.clearStudioRating = function (userId, name) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Studios/" + encodeName(name));
|
||||
|
||||
return self.ajax({
|
||||
type: "DELETE",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
self.clearGenreRating = function (userId, name) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Ratings/Genres/" + encodeName(name));
|
||||
|
||||
return self.ajax({
|
||||
type: "DELETE",
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1828,7 +2076,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Persons/" + encodeName(name) + "/Counts");
|
||||
var url = self.getUrl("Persons/" + encodeName(name) + "/Counts", {
|
||||
userId: userId
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1850,7 +2100,33 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Genres/" + encodeName(name) + "/Counts");
|
||||
var url = self.getUrl("Genres/" + encodeName(name) + "/Counts", {
|
||||
userId: userId
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: "json"
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
Gets a variety of item counts that an artist appears in
|
||||
*/
|
||||
self.getArtistItemCounts = function (userId, name) {
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("null userId");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Artists/" + encodeName(name) + "/Counts", {
|
||||
userId: userId
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
@ -1872,7 +2148,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
|
|||
throw new Error("null name");
|
||||
}
|
||||
|
||||
var url = self.getUrl("Users/" + userId + "/Studios/" + encodeName(name) + "/Counts");
|
||||
var url = self.getUrl("Studios/" + encodeName(name) + "/Counts", {
|
||||
userId: userId
|
||||
});
|
||||
|
||||
return self.ajax({
|
||||
type: "GET",
|
||||
|
|
|
@ -237,6 +237,12 @@
|
|||
<Content Include="dashboard-ui\movietrailers.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\musicalbums.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\musicartists.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\musicgenres.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -288,6 +294,12 @@
|
|||
<Content Include="dashboard-ui\scripts\movietrailers.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\musicalbums.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\musicartists.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\musicgenres.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.80" targetFramework="net45" />
|
||||
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.85" targetFramework="net45" />
|
||||
<package id="ServiceStack.Common" version="3.9.43" targetFramework="net45" />
|
||||
<package id="ServiceStack.Text" version="3.9.43" targetFramework="net45" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user