diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-04-13 14:02:30 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-04-13 14:02:30 -0400 |
| commit | 785deff188ba51243739b827dbe42b5645404367 (patch) | |
| tree | 236515b0e5502b65c6eee3d23412093588c9c5e6 | |
| parent | 6688d35e65352fbf9b0a06a5fdf5a31eaaf425d8 (diff) | |
removed excess hashing in providers and made user data key-based
54 files changed, 512 insertions, 678 deletions
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index cb26688e3..07bbaff74 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -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; diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 9c68df771..5b34119de 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -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); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 3c6731e71..1510dd472 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -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; diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 6801e14f0..42aafd2cd 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -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); } } diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 54561f400..e275b6ed0 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -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; @@ -18,52 +18,14 @@ namespace MediaBrowser.Api.UserLibrary public class GetGenres : GetItemsByName { } - - [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) { } @@ -80,28 +42,6 @@ namespace MediaBrowser.Api.UserLibrary } /// <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> /// <param name="request">The request.</param> diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index aed84e07f..675ac0cd5 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -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)) { diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 4253ddc80..974b8c002 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -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; @@ -22,52 +23,14 @@ namespace MediaBrowser.Api.UserLibrary /// <value>The person types.</value> 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) { } @@ -84,28 +47,6 @@ namespace MediaBrowser.Api.UserLibrary } /// <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> /// <param name="request">The request.</param> diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 24f09c5ef..77f20d8e8 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -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; @@ -17,52 +18,14 @@ namespace MediaBrowser.Api.UserLibrary public class GetStudios : GetItemsByName { } - - [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) { } @@ -77,28 +40,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. diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index e24e63819..70e5287a1 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -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); } } } diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index f2cf36750..481645c24 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -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; @@ -28,9 +29,9 @@ namespace MediaBrowser.Api.UserLibrary /// The us culture /// </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) { } diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 76c67cd2f..3f3af743d 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -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); } diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 9591862e7..b4ad90168 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -56,26 +54,6 @@ namespace MediaBrowser.Common.Extensions } /// <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> /// <param name="str">The STR.</param> diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index ca2891734..f90cd2c0f 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -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 diff --git a/MediaBrowser.Controller/Library/DtoBuilder.cs b/MediaBrowser.Controller/Dto/DtoBuilder.cs index 7f9a6f187..0da4da356 100644 --- a/MediaBrowser.Controller/Library/DtoBuilder.cs +++ b/MediaBrowser.Controller/Dto/DtoBuilder.cs @@ -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,18 +188,19 @@ 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); } } } - + /// <summary> /// Attaches the primary image aspect ratio. /// </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++; @@ -786,49 +789,6 @@ namespace MediaBrowser.Controller.Library } /// <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> /// <param name="id">The id.</param> diff --git a/MediaBrowser.Controller/Dto/UserDtoBuilder.cs b/MediaBrowser.Controller/Dto/UserDtoBuilder.cs new file mode 100644 index 000000000..5c717529a --- /dev/null +++ b/MediaBrowser.Controller/Dto/UserDtoBuilder.cs @@ -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; + } + } +} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 2cb8ac794..ccaabd438 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -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> diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index eefce2fd3..fed6bb7de 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -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); diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index d5e8afb20..619c7a12b 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -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; + } } } diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index d08588077..b70ac2b3b 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -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> diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 5c92c019b..f5570448d 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -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> diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index a255849e6..06511d959 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -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; + } } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 7588e4e69..dd1434cea 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -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 (Series != null) { - if (_userDataId == Guid.Empty) - { - var baseId = Series != null ? Series.GetProviderId(MetadataProviders.Tvdb) ?? Series.GetProviderId(MetadataProviders.Tvcom) : null; - if (baseId != 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; + var seasonNo = Season != null ? Season.IndexNumber ?? 0 : 0; + var epNo = IndexNumber ?? 0; + return Series.GetUserDataKey() + seasonNo.ToString("000") + epNo.ToString("000"); } + + return base.GetUserDataKey(); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 2f2bee172..2f3f7387c 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -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 (Series != null) { - if (_userDataId == Guid.Empty) - { - var baseId = Series != null ? Series.GetProviderId(MetadataProviders.Tvdb) ?? Series.GetProviderId(MetadataProviders.Tvcom) : null; - if (baseId != null) - { - var seasonNo = IndexNumber ?? 0; - baseId = baseId + seasonNo.ToString("000"); - } - - _userDataId = baseId != null ? baseId.GetMD5() : Id; - } - return _userDataId; + var seasonNo = IndexNumber ?? 0; + return Series.GetUserDataKey() + seasonNo.ToString("000"); } + + return base.GetUserDataKey(); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 8a56e45cd..15b97f694 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -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 diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 9150057c8..1e4e6cb06 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -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; + } } } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index ad46cf7c3..0fad1d05d 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -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); } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 558a9d8e3..71245a3bb 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -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" /> diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 592206faf..1b4efc58b 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.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); } } diff --git a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs index aaf3fe6bf..3f71e398a 100644 --- a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs @@ -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(); } @@ -130,8 +119,14 @@ 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; @@ -155,7 +150,7 @@ namespace MediaBrowser.Controller.Providers { SetLastRefreshed(item, value, ProviderVersion, status); } - + /// <summary> /// Returns whether or not this provider should be re-fetched. Default functionality can /// compare a provided date with a last refresh time. This can be overridden for more complex @@ -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> @@ -194,7 +194,7 @@ namespace MediaBrowser.Controller.Providers { throw new ArgumentNullException("providerInfo"); } - + if (CompareDate(item) > providerInfo.LastRefreshed) { return true; @@ -209,7 +209,7 @@ namespace MediaBrowser.Controller.Providers { return true; } - + return false; } @@ -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) { diff --git a/MediaBrowser.Controller/Providers/BaseProviderInfo.cs b/MediaBrowser.Controller/Providers/BaseProviderInfo.cs index 877ba5c4b..5a72491c1 100644 --- a/MediaBrowser.Controller/Providers/BaseProviderInfo.cs +++ b/MediaBrowser.Controller/Providers/BaseProviderInfo.cs @@ -8,11 +8,6 @@ namespace MediaBrowser.Controller.Providers 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> /// <value>The last refreshed.</value> @@ -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> diff --git a/MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs index 3152ceac9..94fe38680 100644 --- a/MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs @@ -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)); diff --git a/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs index fb8370248..8e20f0fad 100644 --- a/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs @@ -22,10 +22,11 @@ namespace MediaBrowser.Controller.Providers.Movies { class MovieDbProviderException : ApplicationException { - public MovieDbProviderException(string msg) : base(msg) + public MovieDbProviderException(string msg) + : base(msg) { } - + } /// <summary> /// Class MovieDbProvider @@ -33,7 +34,7 @@ namespace MediaBrowser.Controller.Providers.Movies public class MovieDbProvider : BaseMetadataProvider, IDisposable { protected readonly IProviderManager ProviderManager; - + /// <summary> /// The movie db /// </summary> @@ -198,7 +199,7 @@ namespace MediaBrowser.Controller.Providers.Movies base_url = "http://cf2.imgobject.com/t/p/" } - }; + }; } } @@ -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; } diff --git a/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs index b53384841..72169f245 100644 --- a/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs @@ -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; + + } } } diff --git a/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs index ec7a96d99..1dd5c7cd2 100644 --- a/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs @@ -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(); diff --git a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs index f58bd3bb7..f7e0eef48 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs @@ -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 diff --git a/MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs index 4d06143fc..a7fc4586f 100644 --- a/MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs +++ b/MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs @@ -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)); diff --git a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs index 76d84a653..d464a64a0 100644 --- a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs @@ -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; } } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index eb2b4ddeb..0c18564ec 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -154,27 +154,6 @@ namespace MediaBrowser.Model.Configuration 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> /// <value>The sort replace characters.</value> @@ -203,13 +182,6 @@ namespace MediaBrowser.Model.Configuration 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> /// <value>The internet provider exclude types.</value> diff --git a/MediaBrowser.Model/Connectivity/ClientConnectionInfo.cs b/MediaBrowser.Model/Connectivity/ClientConnectionInfo.cs index 565ce6ec2..a5e44f22e 100644 --- a/MediaBrowser.Model/Connectivity/ClientConnectionInfo.cs +++ b/MediaBrowser.Model/Connectivity/ClientConnectionInfo.cs @@ -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. diff --git a/MediaBrowser.Model/DTO/UserDto.cs b/MediaBrowser.Model/DTO/UserDto.cs index 979422dbe..b2afa90c0 100644 --- a/MediaBrowser.Model/DTO/UserDto.cs +++ b/MediaBrowser.Model/DTO/UserDto.cs @@ -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. diff --git a/MediaBrowser.Model/Plugins/PluginInfo.cs b/MediaBrowser.Model/Plugins/PluginInfo.cs index 2df635db0..fd4cfa78c 100644 --- a/MediaBrowser.Model/Plugins/PluginInfo.cs +++ b/MediaBrowser.Model/Plugins/PluginInfo.cs @@ -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 diff --git a/MediaBrowser.Model/Querying/ItemQuery.cs b/MediaBrowser.Model/Querying/ItemQuery.cs index 3a1d14065..86886d751 100644 --- a/MediaBrowser.Model/Querying/ItemQuery.cs +++ b/MediaBrowser.Model/Querying/ItemQuery.cs @@ -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. diff --git a/MediaBrowser.Model/Querying/ItemsByNameQuery.cs b/MediaBrowser.Model/Querying/ItemsByNameQuery.cs index 0bebb085e..eae2dc042 100644 --- a/MediaBrowser.Model/Querying/ItemsByNameQuery.cs +++ b/MediaBrowser.Model/Querying/ItemsByNameQuery.cs @@ -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> diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 20716ecc5..afe074088 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -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; } } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index d397b1548..3bb5472df 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -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; } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 311a31264..dbb2d7b32 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -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(); - } } } diff --git a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs index 8b135db5a..ff7222e7c 100644 --- a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs +++ b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs @@ -89,12 +89,6 @@ namespace MediaBrowser.Server.Implementations.Providers } /// <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> /// <param name="providers">The providers.</param> @@ -104,6 +98,11 @@ namespace MediaBrowser.Server.Implementations.Providers } /// <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> /// <param name="item">The item.</param> @@ -126,19 +125,14 @@ namespace MediaBrowser.Server.Implementations.Providers BaseProviderInfo supportedProvidersInfo; - if (SupportedProvidersKey == Guid.Empty) - { - SupportedProvidersKey = "SupportedProviders".GetMD5(); - } - - var supportedProvidersHash = string.Join("+", supportedProviders.Select(i => i.GetType().Name)).GetMD5(); - bool providersChanged = false; + var supportedProvidersValue = string.Join("+", supportedProviders.Select(i => i.GetType().Name)); + var 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; diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index 905d5413a..c634c760e 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -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; @@ -24,6 +25,12 @@ namespace MediaBrowser.Server.Implementations.Sorting 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> /// <param name="x">The x.</param> @@ -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) { diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs index 82e76e78d..a7cbd2149 100644 --- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs @@ -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; } @@ -49,6 +50,12 @@ namespace MediaBrowser.Server.Implementations.Sorting } /// <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> /// <value>The user manager.</value> diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs index 501635800..fbb0e4f8c 100644 --- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs @@ -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 diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs index 467628a78..4df81aacc 100644 --- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs @@ -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"); } + + return _userData.GetOrAdd(key, keyName => RetrieveUserData(userId, key)); + } + /// <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 id = @id and userId=@userId"; + cmd.CommandText = "select data from userdata where key = @key and userId=@userId"; - var idParam = cmd.Parameters.Add("@id", DbType.Guid); - idParam.Value = userDataId; + var idParam = cmd.Parameters.Add("@key", DbType.Guid); + 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(); } } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index afc68fe67..59395e469 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -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; @@ -153,6 +154,12 @@ namespace MediaBrowser.ServerApplication 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> protected override string ProductShortcutPath @@ -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. diff --git a/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs b/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs index 98d7fb477..19c42e8d8 100644 --- a/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs +++ b/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs @@ -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); } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 7756fb5b9..c773503b0 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -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 { |
