Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
commit
6b47336da3
|
@ -2,6 +2,7 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
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;
|
||||
|
@ -104,16 +106,16 @@ namespace MediaBrowser.Api.Library
|
|||
/// </summary>
|
||||
private readonly IApplicationHost _appHost;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IUserManager _userManager;
|
||||
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="userManager">The user manager.</param>
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
/// <exception cref="System.ArgumentNullException">appHost</exception>
|
||||
public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager, IUserManager userManager)
|
||||
public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
{
|
||||
if (appHost == null)
|
||||
{
|
||||
|
@ -122,7 +124,7 @@ namespace MediaBrowser.Api.Library
|
|||
|
||||
_appHost = appHost;
|
||||
_libraryManager = libraryManager;
|
||||
_userManager = userManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -137,7 +139,7 @@ namespace MediaBrowser.Api.Library
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
@ -154,7 +156,7 @@ namespace MediaBrowser.Api.Library
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
@ -171,7 +173,7 @@ namespace MediaBrowser.Api.Library
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
@ -188,7 +190,7 @@ namespace MediaBrowser.Api.Library
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userDataRepository).GetBaseItemDto(item, fields.ToList()).Result;
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers.MediaInfo;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Threading;
|
||||
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;
|
||||
|
@ -8,6 +9,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Api.UserLibrary
|
||||
|
@ -27,16 +29,19 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// The library manager
|
||||
/// </summary>
|
||||
protected readonly ILibraryManager LibraryManager;
|
||||
protected readonly IUserDataRepository UserDataRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseItemsByNameService{TItemType}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
protected BaseItemsByNameService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
protected BaseItemsByNameService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
{
|
||||
UserManager = userManager;
|
||||
LibraryManager = libraryManager;
|
||||
UserDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -132,18 +137,19 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
private IEnumerable<BaseItem> FilterItems(GetItemsByName request, IEnumerable<BaseItem> items, User user)
|
||||
{
|
||||
items = items.AsParallel();
|
||||
|
||||
items = ItemsService.ApplyAdditionalFilters(request, items);
|
||||
|
||||
// Apply filters
|
||||
// Run them starting with the ones that are likely to reduce the list the most
|
||||
foreach (var filter in request.GetFilters().OrderByDescending(f => (int)f))
|
||||
// Exclude item types
|
||||
if (!string.IsNullOrEmpty(request.ExcludeItemTypes))
|
||||
{
|
||||
items = ItemsService.ApplyFilter(items, filter, user, UserManager);
|
||||
var vals = request.ExcludeItemTypes.Split(',');
|
||||
items = items.Where(f => !vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
items = items.AsEnumerable();
|
||||
// Include item types
|
||||
if (!string.IsNullOrEmpty(request.IncludeItemTypes))
|
||||
{
|
||||
var vals = request.IncludeItemTypes.Split(',');
|
||||
items = items.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
@ -185,7 +191,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return null;
|
||||
}
|
||||
|
||||
var dto = await new DtoBuilder(Logger, LibraryManager, UserManager).GetBaseItemDto(item, user, fields).ConfigureAwait(false);
|
||||
var dto = await new DtoBuilder(Logger, LibraryManager, UserDataRepository).GetBaseItemDto(item, user, fields).ConfigureAwait(false);
|
||||
|
||||
if (fields.Contains(ItemFields.ItemCounts))
|
||||
{
|
||||
|
@ -211,13 +217,15 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var item = await getItem().ConfigureAwait(false);
|
||||
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
// Get the user data for this item
|
||||
var data = await UserManager.GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
|
||||
var data = await UserDataRepository.GetUserData(user.Id, key).ConfigureAwait(false);
|
||||
|
||||
// Set favorite status
|
||||
data.IsFavorite = isFavorite;
|
||||
|
||||
await UserManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false);
|
||||
await UserDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Threading;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using ServiceStack.ServiceHost;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -19,51 +19,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoriteGenres/{Name}", "POST")]
|
||||
[Api(Description = "Marks a genre as a favorite")]
|
||||
public class MarkFavoriteGenre : 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 = "POST")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoriteGenres/{Name}", "DELETE")]
|
||||
[Api(Description = "Unmarks a genre as a favorite")]
|
||||
public class UnmarkFavoriteGenre : 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 = "DELETE")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class GenresService
|
||||
/// </summary>
|
||||
public class GenresService : BaseItemsByNameService<Genre>
|
||||
{
|
||||
public GenresService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
: base(userManager, libraryManager)
|
||||
public GenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
: base(userManager, libraryManager, userDataRepository)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -79,28 +41,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Post(MarkFavoriteGenre request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetGenre(request.Name), request.UserId, true);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Delete(UnmarkFavoriteGenre request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetGenre(request.Name), request.UserId, false);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all items.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using ServiceStack.ServiceHost;
|
||||
|
@ -148,6 +150,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// The _user manager
|
||||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
|
@ -161,11 +164,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="searchEngine">The search engine.</param>
|
||||
public ItemsService(IUserManager userManager, ILibraryManager libraryManager, ILibrarySearchEngine searchEngine)
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
public ItemsService(IUserManager userManager, ILibraryManager libraryManager, ILibrarySearchEngine searchEngine, IUserDataRepository userDataRepository)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_libraryManager = libraryManager;
|
||||
_searchEngine = searchEngine;
|
||||
_userDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -199,7 +204,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
// Run them starting with the ones that are likely to reduce the list the most
|
||||
foreach (var filter in request.GetFilters().OrderByDescending(f => (int)f))
|
||||
{
|
||||
items = ApplyFilter(items, filter, user, _userManager);
|
||||
items = ApplyFilter(items, filter, user, _userDataRepository);
|
||||
}
|
||||
|
||||
items = items.AsEnumerable();
|
||||
|
@ -214,7 +219,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var fields = request.GetItemFields().ToList();
|
||||
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository);
|
||||
|
||||
var returnItems = await Task.WhenAll(pagedItems.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields))).ConfigureAwait(false);
|
||||
|
||||
|
@ -274,9 +279,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <param name="items">The items.</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="repository">The repository.</param>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
internal static IEnumerable<BaseItem> ApplyFilter(IEnumerable<BaseItem> items, ItemFilter filter, User user, IUserManager userManager)
|
||||
internal static IEnumerable<BaseItem> ApplyFilter(IEnumerable<BaseItem> items, ItemFilter filter, User user, IUserDataRepository repository)
|
||||
{
|
||||
// Avoids implicitly captured closure
|
||||
var currentUser = user;
|
||||
|
@ -286,7 +291,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.Likes:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
|
||||
});
|
||||
|
@ -294,7 +299,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.Dislikes:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
|
||||
});
|
||||
|
@ -302,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.IsFavorite:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata != null && userdata.IsFavorite;
|
||||
});
|
||||
|
@ -313,7 +318,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.IsResumable:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata != null && userdata.PlaybackPositionTicks > 0;
|
||||
});
|
||||
|
@ -321,7 +326,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.IsPlayed:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata != null && userdata.PlayCount > 0;
|
||||
});
|
||||
|
@ -329,7 +334,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
case ItemFilter.IsUnplayed:
|
||||
return items.Where(item =>
|
||||
{
|
||||
var userdata = userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey()).Result;
|
||||
|
||||
return userdata == null || userdata.PlayCount == 0;
|
||||
});
|
||||
|
@ -347,32 +352,11 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Applies the additional filters.
|
||||
/// </summary>
|
||||
/// <param name="itemsRequest">The items request.</param>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
internal static IEnumerable<BaseItem> ApplyAdditionalFilters(BaseItemsRequest itemsRequest, IEnumerable<BaseItem> items)
|
||||
internal static IEnumerable<BaseItem> ApplyAdditionalFilters(GetItems request, IEnumerable<BaseItem> items)
|
||||
{
|
||||
// Exclude item types
|
||||
if (!string.IsNullOrEmpty(itemsRequest.ExcludeItemTypes))
|
||||
{
|
||||
var vals = itemsRequest.ExcludeItemTypes.Split(',');
|
||||
items = items.Where(f => !vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
// Include item types
|
||||
if (!string.IsNullOrEmpty(itemsRequest.IncludeItemTypes))
|
||||
{
|
||||
var vals = itemsRequest.IncludeItemTypes.Split(',');
|
||||
items = items.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
var request = itemsRequest as GetItems;
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
// Filter by Series Status
|
||||
if (!string.IsNullOrEmpty(request.SeriesStatus))
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using ServiceStack.ServiceHost;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -23,51 +24,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
public string PersonTypes { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoritePersons/{Name}", "POST")]
|
||||
[Api(Description = "Marks a person as a favorite")]
|
||||
public class MarkFavoritePerson : 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 = "POST")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoritePersons/{Name}", "DELETE")]
|
||||
[Api(Description = "Unmarks a person as a favorite")]
|
||||
public class UnmarkFavoritePerson : 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 = "DELETE")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class PersonsService
|
||||
/// </summary>
|
||||
public class PersonsService : BaseItemsByNameService<Person>
|
||||
{
|
||||
public PersonsService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
: base(userManager, libraryManager)
|
||||
public PersonsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
: base(userManager, libraryManager, userDataRepository)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -83,28 +46,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Post(MarkFavoritePerson request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetPerson(request.Name), request.UserId, true);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Delete(UnmarkFavoritePerson request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetPerson(request.Name), request.UserId, false);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all items.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using ServiceStack.ServiceHost;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -18,51 +19,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoriteStudios/{Name}", "POST")]
|
||||
[Api(Description = "Marks a studio as a favorite")]
|
||||
public class MarkFavoriteStudio : 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 = "POST")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Users/{UserId}/FavoriteStudios/{Name}", "DELETE")]
|
||||
[Api(Description = "Unmarks a studio as a favorite")]
|
||||
public class UnmarkFavoriteStudio : 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 = "DELETE")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class StudiosService
|
||||
/// </summary>
|
||||
public class StudiosService : BaseItemsByNameService<Studio>
|
||||
{
|
||||
public StudiosService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
: base(userManager, libraryManager)
|
||||
public StudiosService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
: base(userManager, libraryManager, userDataRepository)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -78,28 +41,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Post(MarkFavoriteStudio request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetStudio(request.Name), request.UserId, true);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified request.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void Delete(UnmarkFavoriteStudio request)
|
||||
{
|
||||
var task = MarkFavorite(() => LibraryManager.GetStudio(request.Name), request.UserId, false);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all items.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using ServiceStack.ServiceHost;
|
||||
|
@ -335,18 +337,19 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// The _user manager
|
||||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserLibraryService" /> class.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
|
||||
public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
: base()
|
||||
{
|
||||
_userManager = userManager;
|
||||
_libraryManager = libraryManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -365,7 +368,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var movie = (Movie)item;
|
||||
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository);
|
||||
|
||||
var items = movie.SpecialFeatures.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields)).AsParallel().Select(t => t.Result).ToList();
|
||||
|
||||
|
@ -386,7 +389,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
|
||||
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository);
|
||||
|
||||
var items = item.LocalTrailers.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields)).AsParallel().Select(t => t.Result).ToList();
|
||||
|
||||
|
@ -407,7 +410,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
|
||||
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository);
|
||||
|
||||
var result = dtoBuilder.GetBaseItemDto(item, user, fields).Result;
|
||||
|
||||
|
@ -423,7 +426,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
// Get everything
|
||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
|
||||
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository);
|
||||
|
||||
var result = dtoBuilder.GetBaseItemDto(item, user, fields).Result;
|
||||
|
||||
|
@ -457,12 +460,14 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
|
||||
|
||||
// Get the user data for this item
|
||||
var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
var data = _userDataRepository.GetUserData(user.Id, key).Result;
|
||||
|
||||
// Set favorite status
|
||||
data.IsFavorite = true;
|
||||
|
||||
var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
|
||||
var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
@ -477,13 +482,15 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
|
||||
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
// Get the user data for this item
|
||||
var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var data = _userDataRepository.GetUserData(user.Id, key).Result;
|
||||
|
||||
// Set favorite status
|
||||
data.IsFavorite = false;
|
||||
|
||||
var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
|
||||
var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
@ -498,12 +505,14 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
|
||||
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
// Get the user data for this item
|
||||
var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var data = _userDataRepository.GetUserData(user.Id, key).Result;
|
||||
|
||||
data.Rating = null;
|
||||
|
||||
var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
|
||||
var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
@ -518,12 +527,14 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
|
||||
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
// Get the user data for this item
|
||||
var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
|
||||
var data = _userDataRepository.GetUserData(user.Id, key).Result;
|
||||
|
||||
data.Likes = request.Likes;
|
||||
|
||||
var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
|
||||
var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
@ -623,7 +634,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
{
|
||||
var item = DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
|
||||
|
||||
return item.SetPlayedStatus(user, wasPlayed, _userManager);
|
||||
return item.SetPlayedStatus(user, wasPlayed, _userDataRepository);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using ServiceStack.ServiceHost;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -29,8 +30,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// </summary>
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
public YearsService(IUserManager userManager, ILibraryManager libraryManager)
|
||||
: base(userManager, libraryManager)
|
||||
public YearsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
: base(userManager, libraryManager, userDataRepository)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
@ -165,7 +166,7 @@ namespace MediaBrowser.Api
|
|||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetUsers request)
|
||||
{
|
||||
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
|
||||
var dtoBuilder = new UserDtoBuilder(Logger);
|
||||
|
||||
var users = _userManager.Users.OrderBy(u => u.Name).Select(dtoBuilder.GetUserDto).ToArray();
|
||||
|
||||
|
@ -186,7 +187,9 @@ namespace MediaBrowser.Api
|
|||
throw new ResourceNotFoundException("User not found");
|
||||
}
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetUserDto(user);
|
||||
var dtoBuilder = new UserDtoBuilder(Logger);
|
||||
|
||||
var result = dtoBuilder.GetUserDto(user);
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
@ -300,7 +303,9 @@ namespace MediaBrowser.Api
|
|||
|
||||
newUser.UpdateConfiguration(dtoUser.Configuration, _xmlSerializer);
|
||||
|
||||
var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetUserDto(newUser);
|
||||
var dtoBuilder = new UserDtoBuilder(Logger);
|
||||
|
||||
var result = dtoBuilder.GetUserDto(newUser);
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -55,26 +53,6 @@ namespace MediaBrowser.Common.Extensions
|
|||
return (aType.FullName + str.ToLower()).GetMD5();
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static U GetValueOrDefault<T, U>(this Dictionary<T, U> dictionary, T key, U defaultValue)
|
||||
{
|
||||
U val;
|
||||
if (!dictionary.TryGetValue(key, out val))
|
||||
{
|
||||
val = defaultValue;
|
||||
}
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attribute value.
|
||||
/// </summary>
|
||||
|
|
|
@ -302,7 +302,7 @@ namespace MediaBrowser.Common.Plugins
|
|||
AssemblyFileName = AssemblyFileName,
|
||||
ConfigurationDateLastModified = ConfigurationDateLastModified,
|
||||
Description = Description,
|
||||
Id = Id,
|
||||
Id = Id.ToString(),
|
||||
EnableAutoUpdate = Configuration.EnableAutoUpdate,
|
||||
UpdateClass = Configuration.UpdateClass,
|
||||
ConfigurationFileName = ConfigurationFileName
|
||||
|
|
|
@ -3,6 +3,8 @@ 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.Drawing;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
@ -14,7 +16,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Library
|
||||
namespace MediaBrowser.Controller.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates DTO's from domain entities
|
||||
|
@ -28,13 +30,13 @@ namespace MediaBrowser.Controller.Library
|
|||
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
public DtoBuilder(ILogger logger, ILibraryManager libraryManager, IUserManager userManager)
|
||||
public DtoBuilder(ILogger logger, ILibraryManager libraryManager, IUserDataRepository userDataRepository)
|
||||
{
|
||||
_logger = logger;
|
||||
_libraryManager = libraryManager;
|
||||
_userManager = userManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -73,7 +75,7 @@ namespace MediaBrowser.Controller.Library
|
|||
{
|
||||
try
|
||||
{
|
||||
AttachPrimaryImageAspectRatio(dto, item);
|
||||
AttachPrimaryImageAspectRatio(dto, item, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -136,7 +138,7 @@ namespace MediaBrowser.Controller.Library
|
|||
{
|
||||
try
|
||||
{
|
||||
AttachPrimaryImageAspectRatio(dto, item);
|
||||
AttachPrimaryImageAspectRatio(dto, item, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -167,7 +169,7 @@ namespace MediaBrowser.Controller.Library
|
|||
{
|
||||
if (fields.Contains(ItemFields.UserData))
|
||||
{
|
||||
var userData = await _userManager.GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
|
||||
var userData = await _userDataRepository.GetUserData(user.Id, item.GetUserDataKey()).ConfigureAwait(false);
|
||||
|
||||
dto.UserData = GetUserItemDataDto(userData);
|
||||
}
|
||||
|
@ -186,7 +188,7 @@ namespace MediaBrowser.Controller.Library
|
|||
// Skip sorting since all we want is a count
|
||||
dto.ChildCount = folder.GetChildren(user).Count();
|
||||
|
||||
await SetSpecialCounts(folder, user, dto, _userManager).ConfigureAwait(false);
|
||||
await SetSpecialCounts(folder, user, dto, _userDataRepository).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,8 +198,9 @@ namespace MediaBrowser.Controller.Library
|
|||
/// </summary>
|
||||
/// <param name="dto">The dto.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="_logger">The _logger.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item)
|
||||
internal static void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item, ILogger _logger)
|
||||
{
|
||||
var path = item.PrimaryImagePath;
|
||||
|
||||
|
@ -503,9 +506,9 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="folder">The folder.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="dto">The dto.</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private static async Task SetSpecialCounts(Folder folder, User user, BaseItemDto dto, IUserManager userManager)
|
||||
private static async Task SetSpecialCounts(Folder folder, User user, BaseItemDto dto, IUserDataRepository userDataRepository)
|
||||
{
|
||||
var rcentlyAddedItemCount = 0;
|
||||
var recursiveItemCount = 0;
|
||||
|
@ -515,7 +518,7 @@ namespace MediaBrowser.Controller.Library
|
|||
// Loop through each recursive child
|
||||
foreach (var child in folder.GetRecursiveChildren(user).Where(i => !i.IsFolder))
|
||||
{
|
||||
var userdata = await userManager.GetUserData(user.Id, child.UserDataId).ConfigureAwait(false);
|
||||
var userdata = await userDataRepository.GetUserData(user.Id, child.GetUserDataKey()).ConfigureAwait(false);
|
||||
|
||||
recursiveItemCount++;
|
||||
|
||||
|
@ -785,49 +788,6 @@ namespace MediaBrowser.Controller.Library
|
|||
return item.Id.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a User to a DTOUser
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>DtoUser.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||
public UserDto GetUserDto(User user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
var dto = new UserDto
|
||||
{
|
||||
Id = user.Id,
|
||||
Name = user.Name,
|
||||
HasPassword = !String.IsNullOrEmpty(user.Password),
|
||||
LastActivityDate = user.LastActivityDate,
|
||||
LastLoginDate = user.LastLoginDate,
|
||||
Configuration = user.Configuration
|
||||
};
|
||||
|
||||
var image = user.PrimaryImagePath;
|
||||
|
||||
if (!string.IsNullOrEmpty(image))
|
||||
{
|
||||
dto.PrimaryImageTag = Kernel.Instance.ImageManager.GetImageCacheTag(user, ImageType.Primary, image);
|
||||
|
||||
try
|
||||
{
|
||||
AttachPrimaryImageAspectRatio(dto, user);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
|
||||
_logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, user.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a BaseItem based upon it's client-side item id
|
||||
/// </summary>
|
71
MediaBrowser.Controller/Dto/UserDtoBuilder.cs
Normal file
71
MediaBrowser.Controller/Dto/UserDtoBuilder.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// Class UserDtoBuilder
|
||||
/// </summary>
|
||||
public class UserDtoBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The _logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDtoBuilder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public UserDtoBuilder(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a User to a DTOUser
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>DtoUser.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||
public UserDto GetUserDto(User user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
var dto = new UserDto
|
||||
{
|
||||
Id = user.Id.ToString(),
|
||||
Name = user.Name,
|
||||
HasPassword = !String.IsNullOrEmpty(user.Password),
|
||||
LastActivityDate = user.LastActivityDate,
|
||||
LastLoginDate = user.LastLoginDate,
|
||||
Configuration = user.Configuration
|
||||
};
|
||||
|
||||
var image = user.PrimaryImagePath;
|
||||
|
||||
if (!string.IsNullOrEmpty(image))
|
||||
{
|
||||
dto.PrimaryImageTag = Kernel.Instance.ImageManager.GetImageCacheTag(user, ImageType.Primary, image);
|
||||
|
||||
try
|
||||
{
|
||||
DtoBuilder.AttachPrimaryImageAspectRatio(dto, user, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
|
||||
_logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, user.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration;
|
|||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
@ -183,23 +184,18 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <summary>
|
||||
/// The _file system stamp
|
||||
/// </summary>
|
||||
private Guid? _fileSystemStamp;
|
||||
private string _fileSystemStamp;
|
||||
/// <summary>
|
||||
/// Gets a directory stamp, in the form of a string, that can be used for
|
||||
/// comparison purposes to determine if the file system entries for this item have changed.
|
||||
/// </summary>
|
||||
/// <value>The file system stamp.</value>
|
||||
[IgnoreDataMember]
|
||||
public Guid FileSystemStamp
|
||||
public string FileSystemStamp
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_fileSystemStamp.HasValue)
|
||||
{
|
||||
_fileSystemStamp = GetFileSystemStamp();
|
||||
}
|
||||
|
||||
return _fileSystemStamp.Value;
|
||||
return _fileSystemStamp ?? (_fileSystemStamp = GetFileSystemStamp());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,12 +217,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// comparison purposes to determine if the file system entries for this item have changed.
|
||||
/// </summary>
|
||||
/// <returns>Guid.</returns>
|
||||
private Guid GetFileSystemStamp()
|
||||
private string GetFileSystemStamp()
|
||||
{
|
||||
// If there's no path or the item is a file, there's nothing to do
|
||||
if (LocationType != LocationType.FileSystem || !ResolveArgs.IsDirectory)
|
||||
{
|
||||
return Guid.Empty;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
@ -242,7 +238,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
sb.Append(file.cFileName);
|
||||
}
|
||||
|
||||
return sb.ToString().GetMD5();
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -820,21 +816,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _user data id
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
protected Guid _userDataId; //cache this so it doesn't have to be re-constructed on every reference
|
||||
/// <summary>
|
||||
/// Return the id that should be used to key user data for this item.
|
||||
/// Default is just this Id but subclasses can use provider Ids for transportability.
|
||||
/// </summary>
|
||||
/// <value>The user data id.</value>
|
||||
[IgnoreDataMember]
|
||||
public virtual Guid UserDataId
|
||||
/// <returns>System.String.</returns>
|
||||
public virtual string GetUserDataKey()
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userDataId == Guid.Empty ? (_userDataId = Id) : _userDataId;
|
||||
}
|
||||
return Id.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1151,14 +1138,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <param name="userManager">The user manager.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public virtual async Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
|
||||
public virtual async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
var data = await userManager.GetUserData(user.Id, UserDataId).ConfigureAwait(false);
|
||||
var key = GetUserDataKey();
|
||||
|
||||
var data = await userManager.GetUserData(user.Id, key).ConfigureAwait(false);
|
||||
|
||||
if (wasPlayed)
|
||||
{
|
||||
|
@ -1181,7 +1170,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
data.Played = wasPlayed;
|
||||
|
||||
await userManager.SaveUserData(user.Id, UserDataId, data, CancellationToken.None).ConfigureAwait(false);
|
||||
await userManager.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Common.Progress;
|
|||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
|
@ -809,7 +810,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
|
||||
public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager)
|
||||
{
|
||||
await base.SetPlayedStatus(user, wasPlayed, userManager).ConfigureAwait(false);
|
||||
|
||||
|
|
|
@ -6,5 +6,13 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public class Genre : BaseItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -30,21 +28,12 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to use tmdb or imdb id so it will stick if the item moves physical locations
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <value>The user data id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid UserDataId
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_userDataId == Guid.Empty)
|
||||
{
|
||||
var baseId = this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb);
|
||||
_userDataId = baseId != null ? baseId.GetMD5() : Id;
|
||||
}
|
||||
return _userDataId;
|
||||
}
|
||||
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.GetUserDataKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -6,6 +6,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public class Person : BaseItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -6,5 +6,13 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public class Studio : BaseItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,27 +49,19 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to use the provider Ids + season and episode number so it will be portable
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <value>The user data id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid UserDataId
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_userDataId == Guid.Empty)
|
||||
{
|
||||
var baseId = Series != null ? Series.GetProviderId(MetadataProviders.Tvdb) ?? Series.GetProviderId(MetadataProviders.Tvcom) : null;
|
||||
if (baseId != null)
|
||||
if (Series != null)
|
||||
{
|
||||
var seasonNo = Season != null ? Season.IndexNumber ?? 0 : 0;
|
||||
var epNo = IndexNumber ?? 0;
|
||||
baseId = baseId + seasonNo.ToString("000") + epNo.ToString("000");
|
||||
}
|
||||
_userDataId = baseId != null ? baseId.GetMD5() : Id;
|
||||
}
|
||||
return _userDataId;
|
||||
return Series.GetUserDataKey() + seasonNo.ToString("000") + epNo.ToString("000");
|
||||
}
|
||||
|
||||
return base.GetUserDataKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -67,27 +67,18 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to use the provider Ids + season number so it will be portable
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <value>The user data id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid UserDataId
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_userDataId == Guid.Empty)
|
||||
{
|
||||
var baseId = Series != null ? Series.GetProviderId(MetadataProviders.Tvdb) ?? Series.GetProviderId(MetadataProviders.Tvcom) : null;
|
||||
if (baseId != null)
|
||||
if (Series != null)
|
||||
{
|
||||
var seasonNo = IndexNumber ?? 0;
|
||||
baseId = baseId + seasonNo.ToString("000");
|
||||
return Series.GetUserDataKey() + seasonNo.ToString("000");
|
||||
}
|
||||
|
||||
_userDataId = baseId != null ? baseId.GetMD5() : Id;
|
||||
}
|
||||
return _userDataId;
|
||||
}
|
||||
return base.GetUserDataKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -44,21 +44,12 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to use the provider Ids so it will be portable
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <value>The user data id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid UserDataId
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_userDataId == Guid.Empty)
|
||||
{
|
||||
var baseId = this.GetProviderId(MetadataProviders.Tvdb) ?? this.GetProviderId(MetadataProviders.Tvcom);
|
||||
_userDataId = baseId != null ? baseId.GetMD5() : Id;
|
||||
}
|
||||
return _userDataId;
|
||||
}
|
||||
return this.GetProviderId(MetadataProviders.Tvdb) ?? this.GetProviderId(MetadataProviders.Tvcom) ?? base.GetUserDataKey();
|
||||
}
|
||||
|
||||
// Studio, Genre and Rating will all be the same so makes no sense to index by these
|
||||
|
|
|
@ -6,5 +6,13 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public class Year : BaseItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,24 +173,5 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="newPassword">The new password.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ChangePassword(User user, string newPassword);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
Task<UserItemData> GetUserData(Guid userId, Guid userDataId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<Compile Include="Drawing\ImageExtensions.cs" />
|
||||
<Compile Include="Drawing\ImageHeader.cs" />
|
||||
<Compile Include="Drawing\ImageManager.cs" />
|
||||
<Compile Include="Dto\UserDtoBuilder.cs" />
|
||||
<Compile Include="Entities\AggregateFolder.cs" />
|
||||
<Compile Include="Entities\Audio\Audio.cs" />
|
||||
<Compile Include="Entities\Audio\MusicAlbum.cs" />
|
||||
|
@ -107,7 +108,7 @@
|
|||
<Compile Include="IServerApplicationHost.cs" />
|
||||
<Compile Include="IServerApplicationPaths.cs" />
|
||||
<Compile Include="Library\ChildrenChangedEventArgs.cs" />
|
||||
<Compile Include="Library\DtoBuilder.cs" />
|
||||
<Compile Include="Dto\DtoBuilder.cs" />
|
||||
<Compile Include="Providers\IProviderManager.cs" />
|
||||
<Compile Include="Providers\MediaInfo\MediaEncoderHelpers.cs" />
|
||||
<Compile Include="Providers\MetadataProviderPriority.cs" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using System;
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -14,19 +14,19 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// Saves the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData,
|
||||
Task SaveUserData(Guid userId, string key, UserItemData userData,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
Task<UserItemData> GetUserData(Guid userId, Guid userDataId);
|
||||
Task<UserItemData> GetUserData(Guid userId, string key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,19 +29,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <summary>
|
||||
/// The _id
|
||||
/// </summary>
|
||||
protected Guid _id;
|
||||
/// <summary>
|
||||
/// Gets the id.
|
||||
/// </summary>
|
||||
/// <value>The id.</value>
|
||||
public virtual Guid Id
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_id == Guid.Empty) _id = GetType().FullName.GetMD5();
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
protected readonly Guid Id;
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
|
@ -105,6 +93,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
Logger = logManager.GetLogger(GetType().Name);
|
||||
LogManager = logManager;
|
||||
ConfigurationManager = configurationManager;
|
||||
Id = GetType().FullName.GetMD5();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
@ -131,7 +120,13 @@ namespace MediaBrowser.Controller.Providers
|
|||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
var data = item.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id });
|
||||
BaseProviderInfo data;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(Id, out data))
|
||||
{
|
||||
data = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
data.LastRefreshed = value;
|
||||
data.LastRefreshStatus = status;
|
||||
data.ProviderVersion = providerVersion;
|
||||
|
@ -171,9 +166,14 @@ namespace MediaBrowser.Controller.Providers
|
|||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
var providerInfo = item.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo());
|
||||
BaseProviderInfo data;
|
||||
|
||||
return NeedsRefreshInternal(item, providerInfo);
|
||||
if (!item.ProviderData.TryGetValue(Id, out data))
|
||||
{
|
||||
data = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
return NeedsRefreshInternal(item, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -221,7 +221,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <returns><c>true</c> if [has file system stamp changed] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||
protected bool HasFileSystemStampChanged(BaseItem item, BaseProviderInfo providerInfo)
|
||||
{
|
||||
return GetCurrentFileSystemStamp(item) != providerInfo.FileSystemStamp;
|
||||
return !string.Equals(GetCurrentFileSystemStamp(item), providerInfo.FileSystemStamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -279,7 +279,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
private Guid GetCurrentFileSystemStamp(BaseItem item)
|
||||
private string GetCurrentFileSystemStamp(BaseItem item)
|
||||
{
|
||||
if (UseParentFileSystemStamp(item) && item.Parent != null)
|
||||
{
|
||||
|
|
|
@ -7,11 +7,6 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// </summary>
|
||||
public class BaseProviderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the provider id.
|
||||
/// </summary>
|
||||
/// <value>The provider id.</value>
|
||||
public Guid ProviderId { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the last refreshed.
|
||||
/// </summary>
|
||||
|
@ -21,7 +16,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// Gets or sets the file system stamp.
|
||||
/// </summary>
|
||||
/// <value>The file system stamp.</value>
|
||||
public Guid FileSystemStamp { get; set; }
|
||||
public string FileSystemStamp { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the last refresh status.
|
||||
/// </summary>
|
||||
|
@ -32,11 +27,6 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// </summary>
|
||||
/// <value>The provider version.</value>
|
||||
public string ProviderVersion { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the data hash.
|
||||
/// </summary>
|
||||
/// <value>The data hash.</value>
|
||||
public Guid DataHash { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -104,7 +104,14 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var movie = item;
|
||||
if (ShouldFetch(movie, movie.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id })))
|
||||
|
||||
BaseProviderInfo providerData;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(Id, out providerData))
|
||||
{
|
||||
providerData = new BaseProviderInfo();
|
||||
}
|
||||
if (ShouldFetch(movie, providerData))
|
||||
{
|
||||
var language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
|
||||
var url = string.Format(FanArtBaseUrl, APIKey, movie.GetProviderId(MetadataProviders.Tmdb));
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
{
|
||||
class MovieDbProviderException : ApplicationException
|
||||
{
|
||||
public MovieDbProviderException(string msg) : base(msg)
|
||||
public MovieDbProviderException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -223,7 +224,14 @@ namespace MediaBrowser.Controller.Providers.Movies
|
|||
//in addition to ours, we need to set the last refreshed time for the local data provider
|
||||
//so it won't see the new files we download and process them all over again
|
||||
if (JsonProvider == null) JsonProvider = new MovieProviderFromJson(LogManager, ConfigurationManager, JsonSerializer, HttpClient, ProviderManager);
|
||||
var data = item.ProviderData.GetValueOrDefault(JsonProvider.Id, new BaseProviderInfo { ProviderId = JsonProvider.Id });
|
||||
|
||||
BaseProviderInfo data;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(JsonProvider.Id, out data))
|
||||
{
|
||||
data = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
data.LastRefreshed = value;
|
||||
item.ProviderData[JsonProvider.Id] = data;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
|
@ -52,14 +53,15 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
|
||||
//Look at our parent for our album cover
|
||||
var artist = (MusicArtist)item.Parent;
|
||||
var cover = artist.AlbumCovers != null ? artist.AlbumCovers.GetValueOrDefault(mbid, null) : null;
|
||||
|
||||
var cover = artist.AlbumCovers != null ? GetValueOrDefault(artist.AlbumCovers, mbid, null) : null;
|
||||
if (cover == null)
|
||||
{
|
||||
// Not there - maybe it is new since artist last refreshed so refresh it and try again
|
||||
await artist.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
cover = artist.AlbumCovers != null ? artist.AlbumCovers.GetValueOrDefault(mbid, null) : null;
|
||||
cover = artist.AlbumCovers != null ? GetValueOrDefault(artist.AlbumCovers, mbid, null) : null;
|
||||
}
|
||||
if (cover == null)
|
||||
{
|
||||
|
@ -71,5 +73,25 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, cover, "folder.jpg", FanArtResourcePool, cancellationToken).ConfigureAwait(false));
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,15 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var artist = (MusicArtist)item;
|
||||
if (ShouldFetch(artist, artist.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id })))
|
||||
|
||||
BaseProviderInfo providerData;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(Id, out providerData))
|
||||
{
|
||||
providerData = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
if (ShouldFetch(artist, providerData))
|
||||
{
|
||||
var url = string.Format(FanArtBaseUrl, APIKey, artist.GetProviderId(MetadataProviders.Musicbrainz));
|
||||
var doc = new XmlDocument();
|
||||
|
|
|
@ -229,7 +229,13 @@ namespace MediaBrowser.Controller.Providers.Music
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var providerData = item.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id });
|
||||
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
|
||||
|
|
|
@ -60,7 +60,15 @@ namespace MediaBrowser.Controller.Providers.TV
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var series = (Series)item;
|
||||
if (ShouldFetch(series, series.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id })))
|
||||
|
||||
BaseProviderInfo providerData;
|
||||
|
||||
if (!item.ProviderData.TryGetValue(Id, out providerData))
|
||||
{
|
||||
providerData = new BaseProviderInfo();
|
||||
}
|
||||
|
||||
if (ShouldFetch(series, providerData))
|
||||
{
|
||||
string language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
|
||||
string url = string.Format(FanArtBaseUrl, APIKey, series.GetProviderId(MetadataProviders.Tvdb));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
|
||||
namespace MediaBrowser.Controller.Sorting
|
||||
{
|
||||
|
@ -19,5 +20,11 @@ namespace MediaBrowser.Controller.Sorting
|
|||
/// </summary>
|
||||
/// <value>The user manager.</value>
|
||||
IUserManager UserManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user data repository.
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
IUserDataRepository UserDataRepository { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,27 +153,6 @@ namespace MediaBrowser.Model.Configuration
|
|||
[ProtoMember(52)]
|
||||
public bool DownloadHDFanArt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the item repository that should be used
|
||||
/// </summary>
|
||||
/// <value>The item repository.</value>
|
||||
[ProtoMember(24)]
|
||||
public string ItemRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the user repository that should be used
|
||||
/// </summary>
|
||||
/// <value>The user repository.</value>
|
||||
[ProtoMember(25)]
|
||||
public string UserRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the user data repository that should be used
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
[ProtoMember(26)]
|
||||
public string UserDataRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Characters to be replaced with a ' ' in strings to create a sort name
|
||||
/// </summary>
|
||||
|
@ -202,13 +181,6 @@ namespace MediaBrowser.Model.Configuration
|
|||
[ProtoMember(30)]
|
||||
public bool ShowLogWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the user data repository that should be used
|
||||
/// </summary>
|
||||
/// <value>The display preferences repository.</value>
|
||||
[ProtoMember(31)]
|
||||
public string DisplayPreferencesRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of types that will NOT be allowed to have internet providers run against them even if they are turned on.
|
||||
/// </summary>
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Connectivity
|
|||
/// </summary>
|
||||
/// <value>The user id.</value>
|
||||
[ProtoMember(1)]
|
||||
public Guid UserId { get; set; }
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the client.
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// </summary>
|
||||
/// <value>The id.</value>
|
||||
[ProtoMember(2)]
|
||||
public Guid Id { get; set; }
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the primary image tag.
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace MediaBrowser.Model.Plugins
|
|||
/// </summary>
|
||||
/// <value>The unique id.</value>
|
||||
[ProtoMember(9)]
|
||||
public Guid Id { get; set; }
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this plug-in should be automatically updated when a
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Querying
|
|||
/// The user to localize search results for
|
||||
/// </summary>
|
||||
/// <value>The user id.</value>
|
||||
public Guid UserId { get; set; }
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specify this to localize the search to a specific item or folder. Omit to use the root.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Model.Querying
|
||||
{
|
||||
|
@ -12,7 +11,7 @@ namespace MediaBrowser.Model.Querying
|
|||
/// Gets or sets the user id.
|
||||
/// </summary>
|
||||
/// <value>The user id.</value>
|
||||
public Guid UserId { get; set; }
|
||||
public string UserId { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the start index.
|
||||
/// </summary>
|
||||
|
|
|
@ -71,6 +71,6 @@ namespace MediaBrowser.Model.System
|
|||
/// </summary>
|
||||
/// <value>The id.</value>
|
||||
[ProtoMember(9)]
|
||||
public Guid Id { get; set; }
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration manager.
|
||||
/// </summary>
|
||||
|
@ -136,12 +138,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
/// <param name="taskManager">The task manager.</param>
|
||||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager)
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataRepository userDataRepository)
|
||||
{
|
||||
_logger = logger;
|
||||
_taskManager = taskManager;
|
||||
_userManager = userManager;
|
||||
ConfigurationManager = configurationManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>();
|
||||
|
||||
ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated;
|
||||
|
@ -903,6 +907,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
userComparer.User = user;
|
||||
userComparer.UserManager = _userManager;
|
||||
userComparer.UserDataRepository = _userDataRepository;
|
||||
|
||||
return userComparer;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using MediaBrowser.Common.Events;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
|
@ -86,20 +87,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IUserDataRepository _userDataRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration manager.
|
||||
/// </summary>
|
||||
/// <value>The configuration manager.</value>
|
||||
private IServerConfigurationManager ConfigurationManager { get; set; }
|
||||
|
||||
private readonly ConcurrentDictionary<string, Task<UserItemData>> _userData = new ConcurrentDictionary<string, Task<UserItemData>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active user data repository
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
public IUserDataRepository UserDataRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active user repository
|
||||
/// </summary>
|
||||
|
@ -321,13 +316,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
var connection = _activeConnections.GetOrAdd(key, keyName => new ClientConnectionInfo
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userId.ToString(),
|
||||
Client = clientType,
|
||||
DeviceName = deviceName,
|
||||
DeviceId = deviceId
|
||||
});
|
||||
|
||||
connection.UserId = userId;
|
||||
connection.UserId = userId.ToString();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
@ -591,12 +586,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, positionTicks);
|
||||
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
if (positionTicks.HasValue)
|
||||
{
|
||||
var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
|
||||
var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false);
|
||||
|
||||
UpdatePlayState(item, data, positionTicks.Value, false);
|
||||
await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false);
|
||||
await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs
|
||||
|
@ -631,7 +628,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item);
|
||||
|
||||
var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
|
||||
var key = item.GetUserDataKey();
|
||||
|
||||
var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false);
|
||||
|
||||
if (positionTicks.HasValue)
|
||||
{
|
||||
|
@ -644,7 +643,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
data.Played = true;
|
||||
}
|
||||
|
||||
await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false);
|
||||
await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs
|
||||
{
|
||||
|
@ -703,59 +702,5 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
data.LastPlayedDate = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves display preferences for an item
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public async Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
|
||||
{
|
||||
var key = userId + userDataId.ToString();
|
||||
try
|
||||
{
|
||||
await UserDataRepository.SaveUserData(userId, userDataId, userData, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var newValue = Task.FromResult(userData);
|
||||
|
||||
// Once it succeeds, put it into the dictionary to make it available to everyone else
|
||||
_userData.AddOrUpdate(key, newValue, delegate { return newValue; });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error saving user data", ex);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
public Task<UserItemData> GetUserData(Guid userId, Guid userDataId)
|
||||
{
|
||||
var key = userId + userDataId.ToString();
|
||||
|
||||
return _userData.GetOrAdd(key, keyName => RetrieveUserData(userId, userDataId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
private async Task<UserItemData> RetrieveUserData(Guid userId, Guid userDataId)
|
||||
{
|
||||
var userdata = await UserDataRepository.GetUserData(userId, userDataId).ConfigureAwait(false);
|
||||
|
||||
return userdata ?? new UserItemData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,12 +88,6 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
Task.Run(() => ValidateCurrentlyRunningProviders());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the supported providers key.
|
||||
/// </summary>
|
||||
/// <value>The supported providers key.</value>
|
||||
private Guid SupportedProvidersKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the metadata providers.
|
||||
/// </summary>
|
||||
|
@ -103,6 +97,11 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
MetadataProviders = providers.OrderBy(e => e.Priority).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _supported providers key
|
||||
/// </summary>
|
||||
private readonly Guid _supportedProvidersKey = "SupportedProviders".GetMD5();
|
||||
|
||||
/// <summary>
|
||||
/// Runs all metadata providers for an entity, and returns true or false indicating if at least one was refreshed and requires persistence
|
||||
/// </summary>
|
||||
|
@ -126,19 +125,14 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
|
||||
BaseProviderInfo supportedProvidersInfo;
|
||||
|
||||
if (SupportedProvidersKey == Guid.Empty)
|
||||
{
|
||||
SupportedProvidersKey = "SupportedProviders".GetMD5();
|
||||
}
|
||||
var supportedProvidersValue = string.Join("+", supportedProviders.Select(i => i.GetType().Name));
|
||||
var providersChanged = false;
|
||||
|
||||
var supportedProvidersHash = string.Join("+", supportedProviders.Select(i => i.GetType().Name)).GetMD5();
|
||||
bool providersChanged = false;
|
||||
|
||||
item.ProviderData.TryGetValue(SupportedProvidersKey, out supportedProvidersInfo);
|
||||
item.ProviderData.TryGetValue(_supportedProvidersKey, out supportedProvidersInfo);
|
||||
if (supportedProvidersInfo != null)
|
||||
{
|
||||
// Force refresh if the supported providers have changed
|
||||
providersChanged = force = force || supportedProvidersInfo.FileSystemStamp != supportedProvidersHash;
|
||||
providersChanged = force = force || !string.Equals(supportedProvidersInfo.FileSystemStamp, supportedProvidersValue);
|
||||
|
||||
// If providers have changed, clear provider info and update the supported providers hash
|
||||
if (providersChanged)
|
||||
|
@ -150,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
|
||||
if (providersChanged)
|
||||
{
|
||||
supportedProvidersInfo.FileSystemStamp = supportedProvidersHash;
|
||||
supportedProvidersInfo.FileSystemStamp = supportedProvidersValue;
|
||||
}
|
||||
|
||||
if (force) item.ClearMetaValues();
|
||||
|
@ -206,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Providers
|
|||
|
||||
if (providersChanged)
|
||||
{
|
||||
item.ProviderData[SupportedProvidersKey] = supportedProvidersInfo;
|
||||
item.ProviderData[_supportedProvidersKey] = supportedProvidersInfo;
|
||||
}
|
||||
|
||||
return result || providersChanged;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System;
|
||||
|
@ -23,6 +24,12 @@ namespace MediaBrowser.Server.Implementations.Sorting
|
|||
/// <value>The user manager.</value>
|
||||
public IUserManager UserManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user data repository.
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
public IUserDataRepository UserDataRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compares the specified x.
|
||||
/// </summary>
|
||||
|
@ -41,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
|
|||
/// <returns>DateTime.</returns>
|
||||
private DateTime GetDate(BaseItem x)
|
||||
{
|
||||
var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result;
|
||||
var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()).Result;
|
||||
|
||||
if (userdata != null && userdata.LastPlayedDate.HasValue)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
|
@ -34,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
|
|||
/// <returns>DateTime.</returns>
|
||||
private int GetValue(BaseItem x)
|
||||
{
|
||||
var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result;
|
||||
var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()).Result;
|
||||
|
||||
return userdata == null ? 0 : userdata.PlayCount;
|
||||
}
|
||||
|
@ -48,6 +49,12 @@ namespace MediaBrowser.Server.Implementations.Sorting
|
|||
get { return ItemSortBy.PlayCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user data repository.
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
public IUserDataRepository UserDataRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user manager.
|
||||
/// </summary>
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
/// <summary>
|
||||
/// Class SQLiteDisplayPreferencesRepository
|
||||
/// </summary>
|
||||
class SQLiteDisplayPreferencesRepository : SqliteRepository, IDisplayPreferencesRepository
|
||||
public class SQLiteDisplayPreferencesRepository : SqliteRepository, IDisplayPreferencesRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// The repository name
|
||||
|
|
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Persistence;
|
|||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
@ -16,6 +17,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
/// </summary>
|
||||
public class SQLiteUserDataRepository : SqliteRepository, IUserDataRepository
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, Task<UserItemData>> _userData = new ConcurrentDictionary<string, Task<UserItemData>>();
|
||||
|
||||
/// <summary>
|
||||
/// The repository name
|
||||
/// </summary>
|
||||
|
@ -45,9 +48,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _protobuf serializer
|
||||
/// </summary>
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
/// <summary>
|
||||
|
@ -90,8 +90,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
|
||||
string[] queries = {
|
||||
|
||||
"create table if not exists userdata (id GUID, userId GUID, data BLOB)",
|
||||
"create unique index if not exists userdataindex on userdata (id, userId)",
|
||||
"create table if not exists userdata (key nvarchar, userId GUID, data BLOB)",
|
||||
"create unique index if not exists userdataindex on userdata (key, userId)",
|
||||
"create table if not exists schema_version (table_name primary key, version)",
|
||||
//pragmas
|
||||
"pragma temp_store = memory"
|
||||
|
@ -104,20 +104,18 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
/// Saves the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// userData
|
||||
/// <exception cref="System.ArgumentNullException">userData
|
||||
/// or
|
||||
/// cancellationToken
|
||||
/// or
|
||||
/// userId
|
||||
/// or
|
||||
/// userDataId
|
||||
/// </exception>
|
||||
public async Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
|
||||
/// userDataId</exception>
|
||||
public async Task SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
||||
{
|
||||
if (userData == null)
|
||||
{
|
||||
|
@ -131,20 +129,49 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
{
|
||||
throw new ArgumentNullException("userId");
|
||||
}
|
||||
if (userDataId == Guid.Empty)
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
throw new ArgumentNullException("userDataId");
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
await PersistUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var newValue = Task.FromResult(userData);
|
||||
|
||||
// Once it succeeds, put it into the dictionary to make it available to everyone else
|
||||
_userData.AddOrUpdate(key, newValue, delegate { return newValue; });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error saving user data", ex);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Persists the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public async Task PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var serialized = _jsonSerializer.SerializeToBytes(userData);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = "replace into userdata (id, userId, data) values (@1, @2, @3)";
|
||||
cmd.AddParam("@1", userDataId);
|
||||
cmd.CommandText = "replace into userdata (key, userId, data) values (@1, @2, @3)";
|
||||
cmd.AddParam("@1", key);
|
||||
cmd.AddParam("@2", userId);
|
||||
cmd.AddParam("@3", serialized);
|
||||
|
||||
|
@ -174,29 +201,40 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
/// Gets the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userDataId">The user data id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// userId
|
||||
/// or
|
||||
/// userDataId
|
||||
/// key
|
||||
/// </exception>
|
||||
public async Task<UserItemData> GetUserData(Guid userId, Guid userDataId)
|
||||
public Task<UserItemData> GetUserData(Guid userId, string key)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentNullException("userId");
|
||||
}
|
||||
if (userDataId == Guid.Empty)
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
throw new ArgumentNullException("userDataId");
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = "select data from userdata where id = @id and userId=@userId";
|
||||
return _userData.GetOrAdd(key, keyName => RetrieveUserData(userId, key));
|
||||
}
|
||||
|
||||
var idParam = cmd.Parameters.Add("@id", DbType.Guid);
|
||||
idParam.Value = userDataId;
|
||||
/// <summary>
|
||||
/// Retrieves the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
private async Task<UserItemData> RetrieveUserData(Guid userId, string key)
|
||||
{
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = "select data from userdata where key = @key and userId=@userId";
|
||||
|
||||
var idParam = cmd.Parameters.Add("@key", DbType.String);
|
||||
idParam.Value = key;
|
||||
|
||||
var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid);
|
||||
userIdParam.Value = userId;
|
||||
|
@ -212,7 +250,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
|
|||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return new UserItemData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ using MediaBrowser.Server.Implementations.Library;
|
|||
using MediaBrowser.Server.Implementations.MediaEncoder;
|
||||
using MediaBrowser.Server.Implementations.Providers;
|
||||
using MediaBrowser.Server.Implementations.ServerManager;
|
||||
using MediaBrowser.Server.Implementations.Sqlite;
|
||||
using MediaBrowser.Server.Implementations.Udp;
|
||||
using MediaBrowser.Server.Implementations.Updates;
|
||||
using MediaBrowser.Server.Implementations.WebSocket;
|
||||
|
@ -152,6 +153,12 @@ namespace MediaBrowser.ServerApplication
|
|||
/// <value>The media encoder.</value>
|
||||
private IMediaEncoder MediaEncoder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user data repository.
|
||||
/// </summary>
|
||||
/// <value>The user data repository.</value>
|
||||
private IUserDataRepository UserDataRepository { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full path to our startmenu shortcut
|
||||
/// </summary>
|
||||
|
@ -216,7 +223,10 @@ namespace MediaBrowser.ServerApplication
|
|||
UserManager = new UserManager(Logger, ServerConfigurationManager);
|
||||
RegisterSingleInstance(UserManager);
|
||||
|
||||
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager);
|
||||
UserDataRepository = new SQLiteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager);
|
||||
RegisterSingleInstance(UserDataRepository);
|
||||
|
||||
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataRepository);
|
||||
RegisterSingleInstance(LibraryManager);
|
||||
|
||||
InstallationManager = new InstallationManager(HttpClient, PackageManager, JsonSerializer, Logger, this);
|
||||
|
@ -273,9 +283,7 @@ namespace MediaBrowser.ServerApplication
|
|||
/// <returns>Task.</returns>
|
||||
private async Task ConfigureDisplayPreferencesRepositories()
|
||||
{
|
||||
var repositories = GetExports<IDisplayPreferencesRepository>();
|
||||
|
||||
var repository = GetRepository(repositories, ServerConfigurationManager.Configuration.DisplayPreferencesRepository);
|
||||
var repository = new SQLiteDisplayPreferencesRepository(ApplicationPaths, JsonSerializer, LogManager);
|
||||
|
||||
await repository.Initialize().ConfigureAwait(false);
|
||||
|
||||
|
@ -288,9 +296,7 @@ namespace MediaBrowser.ServerApplication
|
|||
/// <returns>Task.</returns>
|
||||
private async Task ConfigureItemRepositories()
|
||||
{
|
||||
var repositories = GetExports<IItemRepository>();
|
||||
|
||||
var repository = GetRepository(repositories, ServerConfigurationManager.Configuration.ItemRepository);
|
||||
var repository = new SQLiteItemRepository(ApplicationPaths, JsonSerializer, LogManager);
|
||||
|
||||
await repository.Initialize().ConfigureAwait(false);
|
||||
|
||||
|
@ -301,22 +307,14 @@ namespace MediaBrowser.ServerApplication
|
|||
/// Configures the user data repositories.
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task ConfigureUserDataRepositories()
|
||||
private Task ConfigureUserDataRepositories()
|
||||
{
|
||||
var repositories = GetExports<IUserDataRepository>();
|
||||
|
||||
var repository = GetRepository(repositories, ServerConfigurationManager.Configuration.UserDataRepository);
|
||||
|
||||
await repository.Initialize().ConfigureAwait(false);
|
||||
|
||||
((UserManager)UserManager).UserDataRepository = repository;
|
||||
return UserDataRepository.Initialize();
|
||||
}
|
||||
|
||||
private async Task ConfigureUserRepositories()
|
||||
{
|
||||
var repositories = GetExports<IUserRepository>();
|
||||
|
||||
var repository = GetRepository(repositories, ServerConfigurationManager.Configuration.UserRepository);
|
||||
var repository = new SQLiteUserRepository(ApplicationPaths, JsonSerializer, LogManager);
|
||||
|
||||
await repository.Initialize().ConfigureAwait(false);
|
||||
|
||||
|
@ -470,7 +468,7 @@ namespace MediaBrowser.ServerApplication
|
|||
yield return GetType().Assembly;
|
||||
}
|
||||
|
||||
private readonly Guid _systemId = Environment.MachineName.GetMD5();
|
||||
private readonly string _systemId = Environment.MachineName.GetMD5().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the system status.
|
||||
|
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Common.Net;
|
|||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
|
@ -174,7 +175,7 @@ namespace MediaBrowser.ServerApplication.EntryPoints
|
|||
/// <param name="e">The e.</param>
|
||||
void userManager_UserUpdated(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
var dto = new DtoBuilder(_logger, _libraryManager, _userManager).GetUserDto(e.Argument);
|
||||
var dto = new UserDtoBuilder(_logger).GetUserDto(e.Argument);
|
||||
|
||||
_serverManager.SendWebSocketMessage("UserUpdated", dto);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using MediaBrowser.Common.Net;
|
|||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
@ -192,9 +193,9 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
{
|
||||
var connections = userManager.RecentConnections.ToArray();
|
||||
|
||||
var dtoBuilder = new DtoBuilder(logger, libraryManager, userManager);
|
||||
var dtoBuilder = new UserDtoBuilder(logger);
|
||||
|
||||
var users = userManager.Users.Where(u => connections.Any(c => c.UserId == u.Id)).Select(dtoBuilder.GetUserDto);
|
||||
var users = userManager.Users.Where(u => connections.Any(c => new Guid(c.UserId) == u.Id)).Select(dtoBuilder.GetUserDto);
|
||||
|
||||
return new DashboardInfo
|
||||
{
|
||||
|
|
|
@ -296,13 +296,16 @@
|
|||
<Content Include="dashboard-ui\scripts\videojsextensions.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\thirdparty\jplayer\jplayer.playlist.min.js">
|
||||
<Content Include="dashboard-ui\thirdparty\video-js\video-js.min.css">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\thirdparty\jplayer\Jplayer.swf">
|
||||
<Content Include="dashboard-ui\thirdparty\video-js\video-js.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\thirdparty\jplayer\jquery.jplayer.min.js">
|
||||
<Content Include="dashboard-ui\thirdparty\video-js\video-js.swf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\thirdparty\video-js\video.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\thirdparty\video-js\video-js.min.css">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common.Internal</id>
|
||||
<version>3.0.71</version>
|
||||
<version>3.0.72</version>
|
||||
<title>MediaBrowser.Common.Internal</title>
|
||||
<authors>Luke</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<description>Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption.</description>
|
||||
<copyright>Copyright © Media Browser 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.71" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.72" />
|
||||
<dependency id="NLog" version="2.0.0.2000" />
|
||||
<dependency id="ServiceStack.Text" version="3.9.38" />
|
||||
<dependency id="protobuf-net" version="2.0.0.621" />
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common</id>
|
||||
<version>3.0.71</version>
|
||||
<version>3.0.72</version>
|
||||
<title>MediaBrowser.Common</title>
|
||||
<authors>Media Browser Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Server.Core</id>
|
||||
<version>3.0.71</version>
|
||||
<version>3.0.72</version>
|
||||
<title>Media Browser.Server.Core</title>
|
||||
<authors>Media Browser Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<description>Contains core components required to build plugins for Media Browser Server.</description>
|
||||
<copyright>Copyright © Media Browser 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.71" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.72" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
|
Loading…
Reference in New Issue
Block a user