Sfoglia il codice sorgente

changes from merge

crobibero 4 anni fa
parent
commit
5c66f9e471
56 ha cambiato i file con 43 aggiunte e 12822 eliminazioni
  1. 0 1
      Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs
  2. 7 3
      Jellyfin.Api/Controllers/ActivityLogController.cs
  3. 0 1
      Jellyfin.Api/Controllers/DashboardController.cs
  4. 0 1
      Jellyfin.Api/Controllers/FilterController.cs
  5. 0 1
      Jellyfin.Api/Controllers/ItemRefreshController.cs
  6. 0 1
      Jellyfin.Api/Controllers/LibraryController.cs
  7. 0 1
      Jellyfin.Api/Controllers/LibraryStructureController.cs
  8. 0 1
      Jellyfin.Api/Controllers/MoviesController.cs
  9. 0 1
      Jellyfin.Api/Controllers/NotificationsController.cs
  10. 35 3
      Jellyfin.Api/Controllers/PackageController.cs
  11. 0 1
      Jellyfin.Api/Controllers/PluginsController.cs
  12. 0 1
      Jellyfin.Api/Controllers/TvShowsController.cs
  13. 1 8
      Jellyfin.Api/Controllers/UserController.cs
  14. 0 1
      Jellyfin.Api/Helpers/TranscodingJobHelper.cs
  15. 0 3
      Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs
  16. 0 340
      MediaBrowser.Api/ChannelService.cs
  17. 0 144
      MediaBrowser.Api/ConfigurationService.cs
  18. 0 103
      MediaBrowser.Api/Devices/DeviceService.cs
  19. 0 101
      MediaBrowser.Api/DisplayPreferencesService.cs
  20. 0 285
      MediaBrowser.Api/EnvironmentService.cs
  21. 0 248
      MediaBrowser.Api/FilterService.cs
  22. 0 277
      MediaBrowser.Api/Images/ImageByNameService.cs
  23. 0 296
      MediaBrowser.Api/Images/RemoteImageService.cs
  24. 0 336
      MediaBrowser.Api/ItemLookupService.cs
  25. 0 1124
      MediaBrowser.Api/Library/LibraryService.cs
  26. 0 412
      MediaBrowser.Api/Library/LibraryStructureService.cs
  27. 0 1287
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  28. 0 111
      MediaBrowser.Api/LocalizationService.cs
  29. 0 104
      MediaBrowser.Api/Movies/CollectionService.cs
  30. 0 414
      MediaBrowser.Api/Movies/MoviesService.cs
  31. 0 88
      MediaBrowser.Api/Movies/TrailersService.cs
  32. 0 132
      MediaBrowser.Api/Music/AlbumsService.cs
  33. 0 196
      MediaBrowser.Api/Music/InstantMixService.cs
  34. 0 197
      MediaBrowser.Api/PackageService.cs
  35. 0 216
      MediaBrowser.Api/PlaylistService.cs
  36. 0 277
      MediaBrowser.Api/PluginService.cs
  37. 0 234
      MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
  38. 0 332
      MediaBrowser.Api/SearchService.cs
  39. 0 499
      MediaBrowser.Api/Sessions/SessionService.cs
  40. 0 302
      MediaBrowser.Api/Subtitles/SubtitleService.cs
  41. 0 103
      MediaBrowser.Api/SuggestionsService.cs
  42. 0 69
      MediaBrowser.Api/System/ActivityLogService.cs
  43. 0 221
      MediaBrowser.Api/System/SystemService.cs
  44. 0 497
      MediaBrowser.Api/TvShowsService.cs
  45. 0 143
      MediaBrowser.Api/UserLibrary/ArtistsService.cs
  46. 0 388
      MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
  47. 0 478
      MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
  48. 0 140
      MediaBrowser.Api/UserLibrary/GenresService.cs
  49. 0 514
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  50. 0 146
      MediaBrowser.Api/UserLibrary/PersonsService.cs
  51. 0 456
      MediaBrowser.Api/UserLibrary/PlaystateService.cs
  52. 0 132
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  53. 0 575
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  54. 0 148
      MediaBrowser.Api/UserLibrary/UserViewsService.cs
  55. 0 131
      MediaBrowser.Api/UserLibrary/YearsService.cs
  56. 0 598
      MediaBrowser.Api/UserService.cs

+ 0 - 1
Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs

@@ -1,5 +1,4 @@
 using System.Threading.Tasks;
-using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Library;
 using Microsoft.AspNetCore.Authorization;

+ 7 - 3
Jellyfin.Api/Controllers/ActivityLogController.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Jellyfin.Api.Constants;
 using Jellyfin.Data.Entities;
@@ -35,6 +34,7 @@ namespace Jellyfin.Api.Controllers
         /// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
         /// <param name="limit">Optional. The maximum number of records to return.</param>
         /// <param name="minDate">Optional. The minimum date. Format = ISO.</param>
+        /// <param name="hasUserId">Optional. Filter log entries if it has user id, or not.</param>
         /// <response code="200">Activity log returned.</response>
         /// <returns>A <see cref="QueryResult{ActivityLogEntry}"/> containing the log entries.</returns>
         [HttpGet("Entries")]
@@ -42,10 +42,14 @@ namespace Jellyfin.Api.Controllers
         public ActionResult<QueryResult<ActivityLogEntry>> GetLogEntries(
             [FromQuery] int? startIndex,
             [FromQuery] int? limit,
-            [FromQuery] DateTime? minDate)
+            [FromQuery] DateTime? minDate,
+            [FromQuery] bool? hasUserId)
         {
             var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
-                entries => entries.Where(entry => entry.DateCreated >= minDate));
+                entries => entries.Where(entry => entry.DateCreated >= minDate
+                                                  && (!hasUserId.HasValue || (hasUserId.Value
+                                                      ? entry.UserId != Guid.Empty
+                                                      : entry.UserId == Guid.Empty))));
 
             return _activityManager.GetPagedResult(filterFunc, startIndex, limit);
         }

+ 0 - 1
Jellyfin.Api/Controllers/DashboardController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
 using Jellyfin.Api.Models;

+ 0 - 1
Jellyfin.Api/Controllers/FilterController.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Jellyfin.Api.Constants;
 using MediaBrowser.Controller.Dto;

+ 0 - 1
Jellyfin.Api/Controllers/ItemRefreshController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.ComponentModel;
-using System.Diagnostics.CodeAnalysis;
 using Jellyfin.Api.Constants;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;

+ 0 - 1
Jellyfin.Api/Controllers/LibraryController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.IO;
 using System.Linq;

+ 0 - 1
Jellyfin.Api/Controllers/LibraryStructureController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.IO;
 using System.Linq;

+ 0 - 1
Jellyfin.Api/Controllers/MoviesController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using Jellyfin.Api.Constants;

+ 0 - 1
Jellyfin.Api/Controllers/NotificationsController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Threading;
 using Jellyfin.Api.Models.NotificationDtos;

+ 35 - 3
Jellyfin.Api/Controllers/PackageController.cs

@@ -5,6 +5,7 @@ using System.Linq;
 using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
 using MediaBrowser.Common.Updates;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Updates;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
@@ -20,14 +21,17 @@ namespace Jellyfin.Api.Controllers
     public class PackageController : BaseJellyfinApiController
     {
         private readonly IInstallationManager _installationManager;
+        private readonly IServerConfigurationManager _serverConfigurationManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="PackageController"/> class.
         /// </summary>
-        /// <param name="installationManager">Instance of <see cref="IInstallationManager"/>Installation Manager.</param>
-        public PackageController(IInstallationManager installationManager)
+        /// <param name="installationManager">Instance of the <see cref="IInstallationManager"/> interface.</param>
+        /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+        public PackageController(IInstallationManager installationManager, IServerConfigurationManager serverConfigurationManager)
         {
             _installationManager = installationManager;
+            _serverConfigurationManager = serverConfigurationManager;
         }
 
         /// <summary>
@@ -110,11 +114,39 @@ namespace Jellyfin.Api.Controllers
         [HttpDelete("/Installing/{packageId}")]
         [Authorize(Policy = Policies.RequiresElevation)]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
-        public IActionResult CancelPackageInstallation(
+        public ActionResult CancelPackageInstallation(
             [FromRoute] [Required] Guid packageId)
         {
             _installationManager.CancelInstallation(packageId);
             return NoContent();
         }
+
+        /// <summary>
+        /// Gets all package repositories.
+        /// </summary>
+        /// <response code="200">Package repositories returned.</response>
+        /// <returns>An <see cref="OkResult"/> containing the list of package repositories.</returns>
+        [HttpGet("/Repositories")]
+        [Authorize(Policy = Policies.DefaultAuthorization)]
+        [ProducesResponseType(StatusCodes.Status200OK)]
+        public ActionResult<IEnumerable<RepositoryInfo>> GetRepositories()
+        {
+            return _serverConfigurationManager.Configuration.PluginRepositories;
+        }
+
+        /// <summary>
+        /// Sets the enabled and existing package repositories.
+        /// </summary>
+        /// <param name="repositoryInfos">The list of package repositories.</param>
+        /// <response code="204">Package repositories saved.</response>
+        /// <returns>A <see cref="NoContentResult"/>.</returns>
+        [HttpOptions("/Repositories")]
+        [Authorize(Policy = Policies.DefaultAuthorization)]
+        [ProducesResponseType(StatusCodes.Status204NoContent)]
+        public ActionResult SetRepositories([FromBody] List<RepositoryInfo> repositoryInfos)
+        {
+            _serverConfigurationManager.Configuration.PluginRepositories = repositoryInfos;
+            return NoContent();
+        }
     }
 }

+ 0 - 1
Jellyfin.Api/Controllers/PluginsController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Text.Json;
 using System.Threading.Tasks;

+ 0 - 1
Jellyfin.Api/Controllers/TvShowsController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using Jellyfin.Api.Constants;

+ 1 - 8
Jellyfin.Api/Controllers/UserController.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
@@ -137,14 +136,8 @@ namespace Jellyfin.Api.Controllers
         public ActionResult DeleteUser([FromRoute] Guid userId)
         {
             var user = _userManager.GetUserById(userId);
-
-            if (user == null)
-            {
-                return NotFound("User not found");
-            }
-
             _sessionManager.RevokeUserTokens(user.Id, null);
-            _userManager.DeleteUser(user);
+            _userManager.DeleteUser(userId);
             return NoContent();
         }
 

+ 0 - 1
Jellyfin.Api/Helpers/TranscodingJobHelper.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Threading;

+ 0 - 3
Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs

@@ -1,10 +1,7 @@
 using System;
-using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
-using System.Linq;
 using System.Threading;
-using System.Threading.Tasks;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Model.Dto;
 using Microsoft.Extensions.Logging;

+ 0 - 340
MediaBrowser.Api/ChannelService.cs

@@ -1,340 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Api.UserLibrary;
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Channels", "GET", Summary = "Gets available channels")]
-    public class GetChannels : IReturn<QueryResult<BaseItemDto>>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "SupportsLatestItems", Description = "Optional. Filter by channels that support getting latest items.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? SupportsLatestItems { get; set; }
-
-        public bool? SupportsMediaDeletion { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether this instance is favorite.
-        /// </summary>
-        /// <value><c>null</c> if [is favorite] contains no value, <c>true</c> if [is favorite]; otherwise, <c>false</c>.</value>
-        public bool? IsFavorite { get; set; }
-    }
-
-    [Route("/Channels/{Id}/Features", "GET", Summary = "Gets features for a channel")]
-    public class GetChannelFeatures : IReturn<ChannelFeatures>
-    {
-        [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Channels/Features", "GET", Summary = "Gets features for a channel")]
-    public class GetAllChannelFeatures : IReturn<ChannelFeatures[]>
-    {
-    }
-
-    [Route("/Channels/{Id}/Items", "GET", Summary = "Gets channel items")]
-    public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
-    {
-        [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "FolderId", Description = "Folder Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string FolderId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SortOrder { get; set; }
-
-        [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Filters { get; set; }
-
-        [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string SortBy { get; set; }
-
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        /// <summary>
-        /// Gets the filters.
-        /// </summary>
-        /// <returns>IEnumerable{ItemFilter}.</returns>
-        public IEnumerable<ItemFilter> GetFilters()
-        {
-            var val = Filters;
-
-            return string.IsNullOrEmpty(val)
-                ? Array.Empty<ItemFilter>()
-                : val.Split(',').Select(v => Enum.Parse<ItemFilter>(v, true));
-        }
-
-        /// <summary>
-        /// Gets the order by.
-        /// </summary>
-        /// <returns>IEnumerable{ItemSortBy}.</returns>
-        public ValueTuple<string, SortOrder>[] GetOrderBy()
-        {
-            return BaseItemsRequest.GetOrderBy(SortBy, SortOrder);
-        }
-    }
-
-    [Route("/Channels/Items/Latest", "GET", Summary = "Gets channel items")]
-    public class GetLatestChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Filters { get; set; }
-
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ChannelIds { get; set; }
-
-        /// <summary>
-        /// Gets the filters.
-        /// </summary>
-        /// <returns>IEnumerable{ItemFilter}.</returns>
-        public IEnumerable<ItemFilter> GetFilters()
-        {
-            return string.IsNullOrEmpty(Filters)
-                ? Array.Empty<ItemFilter>()
-                : Filters.Split(',').Select(v => Enum.Parse<ItemFilter>(v, true));
-        }
-    }
-
-    [Authenticated]
-    public class ChannelService : BaseApiService
-    {
-        private readonly IChannelManager _channelManager;
-        private IUserManager _userManager;
-
-        public ChannelService(
-            ILogger<ChannelService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IChannelManager channelManager,
-            IUserManager userManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _channelManager = channelManager;
-            _userManager = userManager;
-        }
-
-        public object Get(GetAllChannelFeatures request)
-        {
-            var result = _channelManager.GetAllChannelFeatures();
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetChannelFeatures request)
-        {
-            var result = _channelManager.GetChannelFeatures(request.Id);
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetChannels request)
-        {
-            var result = _channelManager.GetChannels(new ChannelQuery
-            {
-                Limit = request.Limit,
-                StartIndex = request.StartIndex,
-                UserId = request.UserId,
-                SupportsLatestItems = request.SupportsLatestItems,
-                SupportsMediaDeletion = request.SupportsMediaDeletion,
-                IsFavorite = request.IsFavorite
-            });
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetChannelItems request)
-        {
-            var user = request.UserId.Equals(Guid.Empty)
-                ? null
-                : _userManager.GetUserById(request.UserId);
-
-            var query = new InternalItemsQuery(user)
-            {
-                Limit = request.Limit,
-                StartIndex = request.StartIndex,
-                ChannelIds = new[] { new Guid(request.Id) },
-                ParentId = string.IsNullOrWhiteSpace(request.FolderId) ? Guid.Empty : new Guid(request.FolderId),
-                OrderBy = request.GetOrderBy(),
-                DtoOptions = new Controller.Dto.DtoOptions
-                {
-                    Fields = request.GetItemFields()
-                }
-            };
-
-            foreach (var filter in request.GetFilters())
-            {
-                switch (filter)
-                {
-                    case ItemFilter.Dislikes:
-                        query.IsLiked = false;
-                        break;
-                    case ItemFilter.IsFavorite:
-                        query.IsFavorite = true;
-                        break;
-                    case ItemFilter.IsFavoriteOrLikes:
-                        query.IsFavoriteOrLiked = true;
-                        break;
-                    case ItemFilter.IsFolder:
-                        query.IsFolder = true;
-                        break;
-                    case ItemFilter.IsNotFolder:
-                        query.IsFolder = false;
-                        break;
-                    case ItemFilter.IsPlayed:
-                        query.IsPlayed = true;
-                        break;
-                    case ItemFilter.IsResumable:
-                        query.IsResumable = true;
-                        break;
-                    case ItemFilter.IsUnplayed:
-                        query.IsPlayed = false;
-                        break;
-                    case ItemFilter.Likes:
-                        query.IsLiked = true;
-                        break;
-                }
-            }
-
-            var result = await _channelManager.GetChannelItems(query, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetLatestChannelItems request)
-        {
-            var user = request.UserId.Equals(Guid.Empty)
-                ? null
-                : _userManager.GetUserById(request.UserId);
-
-            var query = new InternalItemsQuery(user)
-            {
-                Limit = request.Limit,
-                StartIndex = request.StartIndex,
-                ChannelIds = (request.ChannelIds ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToArray(),
-                DtoOptions = new Controller.Dto.DtoOptions
-                {
-                    Fields = request.GetItemFields()
-                }
-            };
-
-            foreach (var filter in request.GetFilters())
-            {
-                switch (filter)
-                {
-                    case ItemFilter.Dislikes:
-                        query.IsLiked = false;
-                        break;
-                    case ItemFilter.IsFavorite:
-                        query.IsFavorite = true;
-                        break;
-                    case ItemFilter.IsFavoriteOrLikes:
-                        query.IsFavoriteOrLiked = true;
-                        break;
-                    case ItemFilter.IsFolder:
-                        query.IsFolder = true;
-                        break;
-                    case ItemFilter.IsNotFolder:
-                        query.IsFolder = false;
-                        break;
-                    case ItemFilter.IsPlayed:
-                        query.IsPlayed = true;
-                        break;
-                    case ItemFilter.IsResumable:
-                        query.IsResumable = true;
-                        break;
-                    case ItemFilter.IsUnplayed:
-                        query.IsPlayed = false;
-                        break;
-                    case ItemFilter.Likes:
-                        query.IsLiked = true;
-                        break;
-                }
-            }
-
-            var result = await _channelManager.GetLatestChannelItems(query, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-    }
-}

+ 0 - 144
MediaBrowser.Api/ConfigurationService.cs

@@ -1,144 +0,0 @@
-using System.IO;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetConfiguration.
-    /// </summary>
-    [Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
-    [Authenticated]
-    public class GetConfiguration : IReturn<ServerConfiguration>
-    {
-    }
-
-    [Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")]
-    [Authenticated(AllowBeforeStartupWizard = true)]
-    public class GetNamedConfiguration
-    {
-        [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Key { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateConfiguration.
-    /// </summary>
-    [Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
-    [Authenticated(Roles = "Admin")]
-    public class UpdateConfiguration : ServerConfiguration, IReturnVoid
-    {
-    }
-
-    [Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")]
-    [Authenticated(Roles = "Admin")]
-    public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream
-    {
-        [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Key { get; set; }
-
-        public Stream RequestStream { get; set; }
-    }
-
-    [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
-    [Authenticated(Roles = "Admin")]
-    public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
-    {
-    }
-
-    [Route("/System/MediaEncoder/Path", "POST", Summary = "Updates the path to the media encoder")]
-    [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
-    public class UpdateMediaEncoderPath : IReturnVoid
-    {
-        [ApiMember(Name = "Path", Description = "Path", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Path { get; set; }
-        [ApiMember(Name = "PathType", Description = "PathType", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string PathType { get; set; }
-    }
-
-    public class ConfigurationService : BaseApiService
-    {
-        /// <summary>
-        /// The _json serializer.
-        /// </summary>
-        private readonly IJsonSerializer _jsonSerializer;
-
-        /// <summary>
-        /// The _configuration manager.
-        /// </summary>
-        private readonly IServerConfigurationManager _configurationManager;
-
-        private readonly IMediaEncoder _mediaEncoder;
-
-        public ConfigurationService(
-            ILogger<ConfigurationService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IJsonSerializer jsonSerializer,
-            IServerConfigurationManager configurationManager,
-            IMediaEncoder mediaEncoder)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _jsonSerializer = jsonSerializer;
-            _configurationManager = configurationManager;
-            _mediaEncoder = mediaEncoder;
-        }
-
-        public void Post(UpdateMediaEncoderPath request)
-        {
-            _mediaEncoder.UpdateEncoderPath(request.Path, request.PathType);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetConfiguration request)
-        {
-            return ToOptimizedResult(_configurationManager.Configuration);
-        }
-
-        public object Get(GetNamedConfiguration request)
-        {
-            var result = _configurationManager.GetConfiguration(request.Key);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified configuraiton.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(UpdateConfiguration request)
-        {
-            // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration
-            var json = _jsonSerializer.SerializeToString(request);
-
-            var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json);
-
-            _configurationManager.ReplaceConfiguration(config);
-        }
-
-        public async Task Post(UpdateNamedConfiguration request)
-        {
-            var key = GetPathValue(2).ToString();
-
-            var configurationType = _configurationManager.GetConfigurationType(key);
-            var configuration = await _jsonSerializer.DeserializeFromStreamAsync(request.RequestStream, configurationType).ConfigureAwait(false);
-
-            _configurationManager.SaveConfiguration(key, configuration);
-        }
-
-        public object Get(GetDefaultMetadataOptions request)
-        {
-            return ToOptimizedResult(new MetadataOptions());
-        }
-    }
-}

+ 0 - 103
MediaBrowser.Api/Devices/DeviceService.cs

@@ -1,103 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Security;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Devices;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Devices
-{
-    [Route("/Devices", "GET", Summary = "Gets all devices")]
-    [Authenticated(Roles = "Admin")]
-    public class GetDevices : DeviceQuery, IReturn<QueryResult<DeviceInfo>>
-    {
-    }
-
-    [Route("/Devices/Info", "GET", Summary = "Gets info for a device")]
-    [Authenticated(Roles = "Admin")]
-    public class GetDeviceInfo : IReturn<DeviceInfo>
-    {
-        [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Devices/Options", "GET", Summary = "Gets options for a device")]
-    [Authenticated(Roles = "Admin")]
-    public class GetDeviceOptions : IReturn<DeviceOptions>
-    {
-        [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Devices", "DELETE", Summary = "Deletes a device")]
-    public class DeleteDevice
-    {
-        [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Devices/Options", "POST", Summary = "Updates device options")]
-    [Authenticated(Roles = "Admin")]
-    public class PostDeviceOptions : DeviceOptions, IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    public class DeviceService : BaseApiService
-    {
-        private readonly IDeviceManager _deviceManager;
-        private readonly IAuthenticationRepository _authRepo;
-        private readonly ISessionManager _sessionManager;
-
-        public DeviceService(
-            ILogger<DeviceService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IDeviceManager deviceManager,
-            IAuthenticationRepository authRepo,
-            ISessionManager sessionManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _deviceManager = deviceManager;
-            _authRepo = authRepo;
-            _sessionManager = sessionManager;
-        }
-
-        public void Post(PostDeviceOptions request)
-        {
-            _deviceManager.UpdateDeviceOptions(request.Id, request);
-        }
-
-        public object Get(GetDevices request)
-        {
-            return ToOptimizedResult(_deviceManager.GetDevices(request));
-        }
-
-        public object Get(GetDeviceInfo request)
-        {
-            return _deviceManager.GetDevice(request.Id);
-        }
-
-        public object Get(GetDeviceOptions request)
-        {
-            return _deviceManager.GetDeviceOptions(request.Id);
-        }
-
-        public void Delete(DeleteDevice request)
-        {
-            var sessions = _authRepo.Get(new AuthenticationInfoQuery
-            {
-                DeviceId = request.Id
-            }).Items;
-
-            foreach (var session in sessions)
-            {
-                _sessionManager.Logout(session);
-            }
-        }
-    }
-}

+ 0 - 101
MediaBrowser.Api/DisplayPreferencesService.cs

@@ -1,101 +0,0 @@
-using System.Threading;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class UpdateDisplayPreferences.
-    /// </summary>
-    [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")]
-    public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "DisplayPreferencesId", Description = "DisplayPreferences Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string DisplayPreferencesId { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string UserId { get; set; }
-    }
-
-    [Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]
-    public class GetDisplayPreferences : IReturn<DisplayPreferences>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
-
-        [ApiMember(Name = "Client", Description = "Client", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Client { get; set; }
-    }
-
-    /// <summary>
-    /// Class DisplayPreferencesService.
-    /// </summary>
-    [Authenticated]
-    public class DisplayPreferencesService : BaseApiService
-    {
-        /// <summary>
-        /// The _display preferences manager.
-        /// </summary>
-        private readonly IDisplayPreferencesRepository _displayPreferencesManager;
-        /// <summary>
-        /// The _json serializer.
-        /// </summary>
-        private readonly IJsonSerializer _jsonSerializer;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DisplayPreferencesService" /> class.
-        /// </summary>
-        /// <param name="jsonSerializer">The json serializer.</param>
-        /// <param name="displayPreferencesManager">The display preferences manager.</param>
-        public DisplayPreferencesService(
-            ILogger<DisplayPreferencesService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IJsonSerializer jsonSerializer,
-            IDisplayPreferencesRepository displayPreferencesManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _jsonSerializer = jsonSerializer;
-            _displayPreferencesManager = displayPreferencesManager;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Get(GetDisplayPreferences request)
-        {
-            var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(UpdateDisplayPreferences request)
-        {
-            // Serialize to json and then back so that the core doesn't see the request dto type
-            var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
-
-            _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None);
-        }
-    }
-}

+ 0 - 285
MediaBrowser.Api/EnvironmentService.cs

@@ -1,285 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetDirectoryContents.
-    /// </summary>
-    [Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")]
-    public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the path.
-        /// </summary>
-        /// <value>The path.</value>
-        [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Path { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [include files].
-        /// </summary>
-        /// <value><c>true</c> if [include files]; otherwise, <c>false</c>.</value>
-        [ApiMember(Name = "IncludeFiles", Description = "An optional filter to include or exclude files from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool IncludeFiles { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [include directories].
-        /// </summary>
-        /// <value><c>true</c> if [include directories]; otherwise, <c>false</c>.</value>
-        [ApiMember(Name = "IncludeDirectories", Description = "An optional filter to include or exclude folders from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool IncludeDirectories { get; set; }
-    }
-
-    [Route("/Environment/ValidatePath", "POST", Summary = "Gets the contents of a given directory in the file system")]
-    public class ValidatePath
-    {
-        /// <summary>
-        /// Gets or sets the path.
-        /// </summary>
-        /// <value>The path.</value>
-        [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Path { get; set; }
-
-        public bool ValidateWriteable { get; set; }
-
-        public bool? IsFile { get; set; }
-    }
-
-    [Obsolete]
-    [Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
-    public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the path.
-        /// </summary>
-        /// <value>The path.</value>
-        [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Path { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetDrives.
-    /// </summary>
-    [Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")]
-    public class GetDrives : IReturn<List<FileSystemEntryInfo>>
-    {
-    }
-
-    /// <summary>
-    /// Class GetNetworkComputers.
-    /// </summary>
-    [Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")]
-    public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
-    {
-    }
-
-    [Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")]
-    public class GetParentPath : IReturn<string>
-    {
-        /// <summary>
-        /// Gets or sets the path.
-        /// </summary>
-        /// <value>The path.</value>
-        [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Path { get; set; }
-    }
-
-    public class DefaultDirectoryBrowserInfo
-    {
-        public string Path { get; set; }
-    }
-
-    [Route("/Environment/DefaultDirectoryBrowser", "GET", Summary = "Gets the parent path of a given path")]
-    public class GetDefaultDirectoryBrowser : IReturn<DefaultDirectoryBrowserInfo>
-    {
-    }
-
-    /// <summary>
-    /// Class EnvironmentService.
-    /// </summary>
-    [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
-    public class EnvironmentService : BaseApiService
-    {
-        private const char UncSeparator = '\\';
-        private const string UncSeparatorString = "\\";
-
-        /// <summary>
-        /// The _network manager.
-        /// </summary>
-        private readonly INetworkManager _networkManager;
-        private readonly IFileSystem _fileSystem;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="EnvironmentService" /> class.
-        /// </summary>
-        /// <param name="networkManager">The network manager.</param>
-        public EnvironmentService(
-            ILogger<EnvironmentService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            INetworkManager networkManager,
-            IFileSystem fileSystem)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _networkManager = networkManager;
-            _fileSystem = fileSystem;
-        }
-
-        public void Post(ValidatePath request)
-        {
-            if (request.IsFile.HasValue)
-            {
-                if (request.IsFile.Value)
-                {
-                    if (!File.Exists(request.Path))
-                    {
-                        throw new FileNotFoundException("File not found", request.Path);
-                    }
-                }
-                else
-                {
-                    if (!Directory.Exists(request.Path))
-                    {
-                        throw new FileNotFoundException("File not found", request.Path);
-                    }
-                }
-            }
-
-            else
-            {
-                if (!File.Exists(request.Path) && !Directory.Exists(request.Path))
-                {
-                    throw new FileNotFoundException("Path not found", request.Path);
-                }
-
-                if (request.ValidateWriteable)
-                {
-                    EnsureWriteAccess(request.Path);
-                }
-            }
-        }
-
-        protected void EnsureWriteAccess(string path)
-        {
-            var file = Path.Combine(path, Guid.NewGuid().ToString());
-
-            File.WriteAllText(file, string.Empty);
-            _fileSystem.DeleteFile(file);
-        }
-
-        public object Get(GetDefaultDirectoryBrowser request) =>
-            ToOptimizedResult(new DefaultDirectoryBrowserInfo { Path = null });
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetDirectoryContents request)
-        {
-            var path = request.Path;
-
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException(nameof(Path));
-            }
-
-            var networkPrefix = UncSeparatorString + UncSeparatorString;
-
-            if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase)
-                && path.LastIndexOf(UncSeparator) == 1)
-            {
-                return ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
-            }
-
-            return ToOptimizedResult(GetFileSystemEntries(request).ToList());
-        }
-
-        [Obsolete]
-        public object Get(GetNetworkShares request)
-            => ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetDrives request)
-        {
-            var result = GetDrives().ToList();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the list that is returned when an empty path is supplied.
-        /// </summary>
-        /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
-        private IEnumerable<FileSystemEntryInfo> GetDrives()
-        {
-            return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Directory));
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetNetworkDevices request)
-            => ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
-
-        /// <summary>
-        /// Gets the file system entries.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
-        private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
-        {
-            var entries = _fileSystem.GetFileSystemEntries(request.Path).OrderBy(i => i.FullName).Where(i =>
-            {
-                var isDirectory = i.IsDirectory;
-
-                if (!request.IncludeFiles && !isDirectory)
-                {
-                    return false;
-                }
-
-                return request.IncludeDirectories || !isDirectory;
-            });
-
-            return entries.Select(f => new FileSystemEntryInfo(f.Name, f.FullName, f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File));
-        }
-
-        public object Get(GetParentPath request)
-        {
-            var parent = Path.GetDirectoryName(request.Path);
-
-            if (string.IsNullOrEmpty(parent))
-            {
-                // Check if unc share
-                var index = request.Path.LastIndexOf(UncSeparator);
-
-                if (index != -1 && request.Path.IndexOf(UncSeparator) == 0)
-                {
-                    parent = request.Path.Substring(0, index);
-
-                    if (string.IsNullOrWhiteSpace(parent.TrimStart(UncSeparator)))
-                    {
-                        parent = null;
-                    }
-                }
-            }
-
-            return parent;
-        }
-    }
-}

+ 0 - 248
MediaBrowser.Api/FilterService.cs

@@ -1,248 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Items/Filters", "GET", Summary = "Gets branding configuration")]
-    public class GetQueryFiltersLegacy : IReturn<QueryFiltersLegacy>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string IncludeItemTypes { get; set; }
-
-        [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string MediaTypes { get; set; }
-
-        public string[] GetMediaTypes()
-        {
-            return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetIncludeItemTypes()
-        {
-            return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-    }
-
-    [Route("/Items/Filters2", "GET", Summary = "Gets branding configuration")]
-    public class GetQueryFilters : IReturn<QueryFilters>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string IncludeItemTypes { get; set; }
-
-        [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string MediaTypes { get; set; }
-
-        public string[] GetMediaTypes()
-        {
-            return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetIncludeItemTypes()
-        {
-            return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public bool? IsAiring { get; set; }
-
-        public bool? IsMovie { get; set; }
-
-        public bool? IsSports { get; set; }
-
-        public bool? IsKids { get; set; }
-
-        public bool? IsNews { get; set; }
-
-        public bool? IsSeries { get; set; }
-
-        public bool? Recursive { get; set; }
-    }
-
-    [Authenticated]
-    public class FilterService : BaseApiService
-    {
-        private readonly ILibraryManager _libraryManager;
-        private readonly IUserManager _userManager;
-
-        public FilterService(
-            ILogger<FilterService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ILibraryManager libraryManager,
-            IUserManager userManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _libraryManager = libraryManager;
-            _userManager = userManager;
-        }
-
-        public object Get(GetQueryFilters request)
-        {
-            var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
-            {
-                parentItem = null;
-            }
-
-            var filters = new QueryFilters();
-
-            var genreQuery = new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = request.GetIncludeItemTypes(),
-                DtoOptions = new Controller.Dto.DtoOptions
-                {
-                    Fields = Array.Empty<ItemFields>(),
-                    EnableImages = false,
-                    EnableUserData = false
-                },
-                IsAiring = request.IsAiring,
-                IsMovie = request.IsMovie,
-                IsSports = request.IsSports,
-                IsKids = request.IsKids,
-                IsNews = request.IsNews,
-                IsSeries = request.IsSeries
-            };
-
-            // Non recursive not yet supported for library folders
-            if ((request.Recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
-            {
-                genreQuery.AncestorIds = parentItem == null ? Array.Empty<Guid>() : new[] { parentItem.Id };
-            }
-            else
-            {
-                genreQuery.Parent = parentItem;
-            }
-
-            if (string.Equals(request.IncludeItemTypes, "MusicAlbum", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "MusicVideo", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "MusicArtist", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "Audio", StringComparison.OrdinalIgnoreCase))
-            {
-                filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
-                {
-                    Name = i.Item1.Name,
-                    Id = i.Item1.Id
-                }).ToArray();
-            }
-            else
-            {
-                filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
-                {
-                    Name = i.Item1.Name,
-                    Id = i.Item1.Id
-                }).ToArray();
-            }
-
-            return ToOptimizedResult(filters);
-        }
-
-        public object Get(GetQueryFiltersLegacy request)
-        {
-            var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
-                string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
-            {
-                parentItem = null;
-            }
-
-            var item = string.IsNullOrEmpty(request.ParentId) ?
-               user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder() :
-               parentItem;
-
-            var result = ((Folder)item).GetItemList(GetItemsQuery(request, user));
-
-            var filters = GetFilters(result);
-
-            return ToOptimizedResult(filters);
-        }
-
-        private QueryFiltersLegacy GetFilters(IReadOnlyCollection<BaseItem> items)
-        {
-            var result = new QueryFiltersLegacy();
-
-            result.Years = items.Select(i => i.ProductionYear ?? -1)
-                .Where(i => i > 0)
-                .Distinct()
-                .OrderBy(i => i)
-                .ToArray();
-
-            result.Genres = items.SelectMany(i => i.Genres)
-                .DistinctNames()
-                .OrderBy(i => i)
-                .ToArray();
-
-            result.Tags = items
-                .SelectMany(i => i.Tags)
-                .Distinct(StringComparer.OrdinalIgnoreCase)
-                .OrderBy(i => i)
-                .ToArray();
-
-            result.OfficialRatings = items
-                .Select(i => i.OfficialRating)
-                .Where(i => !string.IsNullOrWhiteSpace(i))
-                .Distinct(StringComparer.OrdinalIgnoreCase)
-                .OrderBy(i => i)
-                .ToArray();
-
-            return result;
-        }
-
-        private InternalItemsQuery GetItemsQuery(GetQueryFiltersLegacy request, User user)
-        {
-            var query = new InternalItemsQuery
-            {
-                User = user,
-                MediaTypes = request.GetMediaTypes(),
-                IncludeItemTypes = request.GetIncludeItemTypes(),
-                Recursive = true,
-                EnableTotalRecordCount = false,
-                DtoOptions = new Controller.Dto.DtoOptions
-                {
-                    Fields = new[] { ItemFields.Genres, ItemFields.Tags },
-                    EnableImages = false,
-                    EnableUserData = false
-                }
-            };
-
-            return query;
-        }
-    }
-}

+ 0 - 277
MediaBrowser.Api/Images/ImageByNameService.cs

@@ -1,277 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Images
-{
-    /// <summary>
-    /// Class GetGeneralImage.
-    /// </summary>
-    [Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")]
-    public class GetGeneralImage
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        [ApiMember(Name = "Type", Description = "Image Type (primary, backdrop, logo, etc).", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Type { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetRatingImage.
-    /// </summary>
-    [Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")]
-    public class GetRatingImage
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the theme.
-        /// </summary>
-        /// <value>The theme.</value>
-        [ApiMember(Name = "Theme", Description = "The theme to get the image from", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Theme { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetMediaInfoImage.
-    /// </summary>
-    [Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")]
-    public class GetMediaInfoImage
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the theme.
-        /// </summary>
-        /// <value>The theme.</value>
-        [ApiMember(Name = "Theme", Description = "The theme to get the image from", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Theme { get; set; }
-    }
-
-    [Route("/Images/MediaInfo", "GET", Summary = "Gets all media info image by name")]
-    [Authenticated]
-    public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
-    {
-    }
-
-    [Route("/Images/Ratings", "GET", Summary = "Gets all rating images by name")]
-    [Authenticated]
-    public class GetRatingImages : IReturn<List<ImageByNameInfo>>
-    {
-    }
-
-    [Route("/Images/General", "GET", Summary = "Gets all general images by name")]
-    [Authenticated]
-    public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
-    {
-    }
-
-    /// <summary>
-    /// Class ImageByNameService.
-    /// </summary>
-    public class ImageByNameService : BaseApiService
-    {
-        /// <summary>
-        /// The _app paths.
-        /// </summary>
-        private readonly IServerApplicationPaths _appPaths;
-
-        private readonly IFileSystem _fileSystem;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ImageByNameService" /> class.
-        /// </summary>
-        public ImageByNameService(
-            ILogger<ImageByNameService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory resultFactory,
-            IFileSystem fileSystem)
-            : base(logger, serverConfigurationManager, resultFactory)
-        {
-            _appPaths = serverConfigurationManager.ApplicationPaths;
-            _fileSystem = fileSystem;
-        }
-
-        public object Get(GetMediaInfoImages request)
-        {
-            return ToOptimizedResult(GetImageList(_appPaths.MediaInfoImagesPath, true));
-        }
-
-        public object Get(GetRatingImages request)
-        {
-            return ToOptimizedResult(GetImageList(_appPaths.RatingsPath, true));
-        }
-
-        public object Get(GetGeneralImages request)
-        {
-            return ToOptimizedResult(GetImageList(_appPaths.GeneralPath, false));
-        }
-
-        private List<ImageByNameInfo> GetImageList(string path, bool supportsThemes)
-        {
-            try
-            {
-                return _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, true)
-                    .Select(i => new ImageByNameInfo
-                    {
-                        Name = _fileSystem.GetFileNameWithoutExtension(i),
-                        FileLength = i.Length,
-
-                        // For themeable images, use the Theme property
-                        // For general images, the same object structure is fine,
-                        // but it's not owned by a theme, so call it Context
-                        Theme = supportsThemes ? GetThemeName(i.FullName, path) : null,
-                        Context = supportsThemes ? null : GetThemeName(i.FullName, path),
-
-                        Format = i.Extension.ToLowerInvariant().TrimStart('.')
-                    })
-                    .OrderBy(i => i.Name)
-                    .ToList();
-            }
-            catch (IOException)
-            {
-                return new List<ImageByNameInfo>();
-            }
-        }
-
-        private string GetThemeName(string path, string rootImagePath)
-        {
-            var parentName = Path.GetDirectoryName(path);
-
-            if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
-            {
-                return null;
-            }
-
-            parentName = Path.GetFileName(parentName);
-
-            return string.Equals(parentName, "all", StringComparison.OrdinalIgnoreCase) ?
-                null :
-                parentName;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public Task<object> Get(GetGeneralImage request)
-        {
-            var filename = string.Equals(request.Type, "primary", StringComparison.OrdinalIgnoreCase)
-                               ? "folder"
-                               : request.Type;
-
-            var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList();
-
-            var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault();
-
-            return ResultFactory.GetStaticFileResult(Request, path);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetRatingImage request)
-        {
-            var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme);
-
-            if (Directory.Exists(themeFolder))
-            {
-                var path = BaseItem.SupportedImageExtensions
-                    .Select(i => Path.Combine(themeFolder, request.Name + i))
-                    .FirstOrDefault(File.Exists);
-
-                if (!string.IsNullOrEmpty(path))
-                {
-                    return ResultFactory.GetStaticFileResult(Request, path);
-                }
-            }
-
-            var allFolder = Path.Combine(_appPaths.RatingsPath, "all");
-
-            if (Directory.Exists(allFolder))
-            {
-                // Avoid implicitly captured closure
-                var currentRequest = request;
-
-                var path = BaseItem.SupportedImageExtensions
-                    .Select(i => Path.Combine(allFolder, currentRequest.Name + i))
-                    .FirstOrDefault(File.Exists);
-
-                if (!string.IsNullOrEmpty(path))
-                {
-                    return ResultFactory.GetStaticFileResult(Request, path);
-                }
-            }
-
-            throw new ResourceNotFoundException("MediaInfo image not found: " + request.Name);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public Task<object> Get(GetMediaInfoImage request)
-        {
-            var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme);
-
-            if (Directory.Exists(themeFolder))
-            {
-                var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
-                    .FirstOrDefault(File.Exists);
-
-                if (!string.IsNullOrEmpty(path))
-                {
-                    return ResultFactory.GetStaticFileResult(Request, path);
-                }
-            }
-
-            var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all");
-
-            if (Directory.Exists(allFolder))
-            {
-                // Avoid implicitly captured closure
-                var currentRequest = request;
-
-                var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
-                    .FirstOrDefault(File.Exists);
-
-                if (!string.IsNullOrEmpty(path))
-                {
-                    return ResultFactory.GetStaticFileResult(Request, path);
-                }
-            }
-
-            throw new ResourceNotFoundException("MediaInfo image not found: " + request.Name);
-        }
-    }
-}

+ 0 - 296
MediaBrowser.Api/Images/RemoteImageService.cs

@@ -1,296 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Images
-{
-    public class BaseRemoteImageRequest : IReturn<RemoteImageResult>
-    {
-        [ApiMember(Name = "Type", Description = "The image type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public ImageType? Type { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "ProviderName", Description = "Optional. The image provider to use", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ProviderName { get; set; }
-
-        [ApiMember(Name = "IncludeAllLanguages", Description = "Optional.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludeAllLanguages { get; set; }
-    }
-
-    [Route("/Items/{Id}/RemoteImages", "GET", Summary = "Gets available remote images for an item")]
-    [Authenticated]
-    public class GetRemoteImages : BaseRemoteImageRequest
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Items/{Id}/RemoteImages/Providers", "GET", Summary = "Gets available remote image providers for an item")]
-    [Authenticated]
-    public class GetRemoteImageProviders : IReturn<List<ImageProviderInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    public class BaseDownloadRemoteImage : IReturnVoid
-    {
-        [ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public ImageType Type { get; set; }
-
-        [ApiMember(Name = "ProviderName", Description = "The image provider", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string ProviderName { get; set; }
-
-        [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string ImageUrl { get; set; }
-    }
-
-    [Route("/Items/{Id}/RemoteImages/Download", "POST", Summary = "Downloads a remote image for an item")]
-    [Authenticated(Roles = "Admin")]
-    public class DownloadRemoteImage : BaseDownloadRemoteImage
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Images/Remote", "GET", Summary = "Gets a remote image")]
-    public class GetRemoteImage
-    {
-        [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ImageUrl { get; set; }
-    }
-
-    public class RemoteImageService : BaseApiService
-    {
-        private readonly IProviderManager _providerManager;
-
-        private readonly IServerApplicationPaths _appPaths;
-        private readonly IHttpClient _httpClient;
-        private readonly IFileSystem _fileSystem;
-
-        private readonly ILibraryManager _libraryManager;
-
-        public RemoteImageService(
-            ILogger<RemoteImageService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IProviderManager providerManager,
-            IServerApplicationPaths appPaths,
-            IHttpClient httpClient,
-            IFileSystem fileSystem,
-            ILibraryManager libraryManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _providerManager = providerManager;
-            _appPaths = appPaths;
-            _httpClient = httpClient;
-            _fileSystem = fileSystem;
-            _libraryManager = libraryManager;
-        }
-
-        public object Get(GetRemoteImageProviders request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var result = GetImageProviders(item);
-
-            return ToOptimizedResult(result);
-        }
-
-        private List<ImageProviderInfo> GetImageProviders(BaseItem item)
-        {
-            return _providerManager.GetRemoteImageProviderInfo(item).ToList();
-        }
-
-        public async Task<object> Get(GetRemoteImages request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery(request.ProviderName)
-            {
-                IncludeAllLanguages = request.IncludeAllLanguages,
-                IncludeDisabledProviders = true,
-                ImageType = request.Type
-            }, CancellationToken.None).ConfigureAwait(false);
-
-            var imagesList = images.ToArray();
-
-            var allProviders = _providerManager.GetRemoteImageProviderInfo(item);
-
-            if (request.Type.HasValue)
-            {
-                allProviders = allProviders.Where(i => i.SupportedImages.Contains(request.Type.Value));
-            }
-
-            var result = new RemoteImageResult
-            {
-                TotalRecordCount = imagesList.Length,
-                Providers = allProviders.Select(i => i.Name)
-                .Distinct(StringComparer.OrdinalIgnoreCase)
-                .ToArray()
-            };
-
-            if (request.StartIndex.HasValue)
-            {
-                imagesList = imagesList.Skip(request.StartIndex.Value)
-                    .ToArray();
-            }
-
-            if (request.Limit.HasValue)
-            {
-                imagesList = imagesList.Take(request.Limit.Value)
-                    .ToArray();
-            }
-
-            result.Images = imagesList;
-
-            return result;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(DownloadRemoteImage request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            return DownloadRemoteImage(item, request);
-        }
-
-        /// <summary>
-        /// Downloads the remote image.
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <param name="request">The request.</param>
-        /// <returns>Task.</returns>
-        private async Task DownloadRemoteImage(BaseItem item, BaseDownloadRemoteImage request)
-        {
-            await _providerManager.SaveImage(item, request.ImageUrl, request.Type, null, CancellationToken.None).ConfigureAwait(false);
-
-            item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Get(GetRemoteImage request)
-        {
-            var urlHash = request.ImageUrl.GetMD5();
-            var pointerCachePath = GetFullCachePath(urlHash.ToString());
-
-            string contentPath;
-
-            try
-            {
-                contentPath = File.ReadAllText(pointerCachePath);
-
-                if (File.Exists(contentPath))
-                {
-                    return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
-                }
-            }
-            catch (FileNotFoundException)
-            {
-                // Means the file isn't cached yet
-            }
-            catch (IOException)
-            {
-                // Means the file isn't cached yet
-            }
-
-            await DownloadImage(request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
-
-            // Read the pointer file again
-            contentPath = File.ReadAllText(pointerCachePath);
-
-            return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
-        }
-
-        /// <summary>
-        /// Downloads the image.
-        /// </summary>
-        /// <param name="url">The URL.</param>
-        /// <param name="urlHash">The URL hash.</param>
-        /// <param name="pointerCachePath">The pointer cache path.</param>
-        /// <returns>Task.</returns>
-        private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath)
-        {
-            using var result = await _httpClient.GetResponse(new HttpRequestOptions
-            {
-                Url = url,
-                BufferContent = false
-            }).ConfigureAwait(false);
-            var ext = result.ContentType.Split('/')[^1];
-
-            var fullCachePath = GetFullCachePath(urlHash + "." + ext);
-
-            Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
-            var stream = result.Content;
-            await using (stream.ConfigureAwait(false))
-            {
-                var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
-                await using (filestream.ConfigureAwait(false))
-                {
-                    await stream.CopyToAsync(filestream).ConfigureAwait(false);
-                }
-            }
-
-            Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
-            File.WriteAllText(pointerCachePath, fullCachePath);
-        }
-
-        /// <summary>
-        /// Gets the full cache path.
-        /// </summary>
-        /// <param name="filename">The filename.</param>
-        /// <returns>System.String.</returns>
-        private string GetFullCachePath(string filename)
-        {
-            return Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
-        }
-    }
-}

+ 0 - 336
MediaBrowser.Api/ItemLookupService.cs

@@ -1,336 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-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.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Items/{Id}/ExternalIdInfos", "GET", Summary = "Gets external id infos for an item")]
-    [Authenticated(Roles = "Admin")]
-    public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid Id { get; set; }
-    }
-
-    [Route("/Items/RemoteSearch/Movie", "POST")]
-    [Authenticated]
-    public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/Trailer", "POST")]
-    [Authenticated]
-    public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/MusicVideo", "POST")]
-    [Authenticated]
-    public class GetMusicVideoRemoteSearchResults : RemoteSearchQuery<MusicVideoInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/Series", "POST")]
-    [Authenticated]
-    public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/BoxSet", "POST")]
-    [Authenticated]
-    public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/MusicArtist", "POST")]
-    [Authenticated]
-    public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/MusicAlbum", "POST")]
-    [Authenticated]
-    public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/Person", "POST")]
-    [Authenticated(Roles = "Admin")]
-    public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/Book", "POST")]
-    [Authenticated]
-    public class GetBookRemoteSearchResults : RemoteSearchQuery<BookInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
-    [Route("/Items/RemoteSearch/Image", "GET", Summary = "Gets a remote image")]
-    public class GetRemoteSearchImage
-    {
-        [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ImageUrl { get; set; }
-
-        [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ProviderName { get; set; }
-    }
-
-    [Route("/Items/RemoteSearch/Apply/{Id}", "POST", Summary = "Applies search criteria to an item and refreshes metadata")]
-    [Authenticated(Roles = "Admin")]
-    public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "ReplaceAllImages", Description = "Whether or not to replace all images", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
-        public bool ReplaceAllImages { get; set; }
-
-        public ApplySearchCriteria()
-        {
-            ReplaceAllImages = true;
-        }
-    }
-
-    public class ItemLookupService : BaseApiService
-    {
-        private readonly IProviderManager _providerManager;
-        private readonly IServerApplicationPaths _appPaths;
-        private readonly IFileSystem _fileSystem;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IJsonSerializer _json;
-
-        public ItemLookupService(
-            ILogger<ItemLookupService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IProviderManager providerManager,
-            IFileSystem fileSystem,
-            ILibraryManager libraryManager,
-            IJsonSerializer json)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _providerManager = providerManager;
-            _appPaths = serverConfigurationManager.ApplicationPaths;
-            _fileSystem = fileSystem;
-            _libraryManager = libraryManager;
-            _json = json;
-        }
-
-        public object Get(GetExternalIdInfos request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var infos = _providerManager.GetExternalIdInfos(item).ToList();
-
-            return ToOptimizedResult(infos);
-        }
-
-        public async Task<object> Post(GetTrailerRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetBookRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<Book, BookInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetMovieRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetSeriesRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetBoxSetRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetMusicVideoRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<MusicVideo, MusicVideoInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetPersonRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetMusicAlbumRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(GetMusicArtistRemoteSearchResults request)
-        {
-            var result = await _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public Task<object> Get(GetRemoteSearchImage request)
-        {
-            return GetRemoteImage(request);
-        }
-
-        public Task Post(ApplySearchCriteria request)
-        {
-            var item = _libraryManager.GetItemById(new Guid(request.Id));
-
-            // foreach (var key in request.ProviderIds)
-            //{
-            //    var value = key.Value;
-
-            //    if (!string.IsNullOrWhiteSpace(value))
-            //    {
-            //        item.SetProviderId(key.Key, value);
-            //    }
-            //}
-            Logger.LogInformation("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds));
-
-            // Since the refresh process won't erase provider Ids, we need to set this explicitly now.
-            item.ProviderIds = request.ProviderIds;
-            // item.ProductionYear = request.ProductionYear;
-            // item.Name = request.Name;
-
-            return _providerManager.RefreshFullItem(
-                item,
-                new MetadataRefreshOptions(new DirectoryService(_fileSystem))
-                {
-                    MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
-                    ImageRefreshMode = MetadataRefreshMode.FullRefresh,
-                    ReplaceAllMetadata = true,
-                    ReplaceAllImages = request.ReplaceAllImages,
-                    SearchResult = request
-                },
-                CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Gets the remote image.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{System.Object}.</returns>
-        private async Task<object> GetRemoteImage(GetRemoteSearchImage request)
-        {
-            var urlHash = request.ImageUrl.GetMD5();
-            var pointerCachePath = GetFullCachePath(urlHash.ToString());
-
-            string contentPath;
-
-            try
-            {
-                contentPath = File.ReadAllText(pointerCachePath);
-
-                if (File.Exists(contentPath))
-                {
-                    return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
-                }
-            }
-            catch (FileNotFoundException)
-            {
-                // Means the file isn't cached yet
-            }
-            catch (IOException)
-            {
-                // Means the file isn't cached yet
-            }
-
-            await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
-
-            // Read the pointer file again
-            contentPath = File.ReadAllText(pointerCachePath);
-
-            return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
-        }
-
-        /// <summary>
-        /// Downloads the image.
-        /// </summary>
-        /// <param name="providerName">Name of the provider.</param>
-        /// <param name="url">The URL.</param>
-        /// <param name="urlHash">The URL hash.</param>
-        /// <param name="pointerCachePath">The pointer cache path.</param>
-        /// <returns>Task.</returns>
-        private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath)
-        {
-            var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
-
-            var ext = result.ContentType.Split('/')[^1];
-
-            var fullCachePath = GetFullCachePath(urlHash + "." + ext);
-
-            Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
-            var stream = result.Content;
-
-            await using (stream.ConfigureAwait(false))
-            {
-                var fileStream = new FileStream(
-                    fullCachePath,
-                    FileMode.Create,
-                    FileAccess.Write,
-                    FileShare.Read,
-                    IODefaults.FileStreamBufferSize,
-                    true);
-                await using (fileStream.ConfigureAwait(false))
-                {
-                    await stream.CopyToAsync(fileStream).ConfigureAwait(false);
-                }
-            }
-
-            Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
-            File.WriteAllText(pointerCachePath, fullCachePath);
-        }
-
-        /// <summary>
-        /// Gets the full cache path.
-        /// </summary>
-        /// <param name="filename">The filename.</param>
-        /// <returns>System.String.</returns>
-        private string GetFullCachePath(string filename)
-            => Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
-    }
-}

+ 0 - 1124
MediaBrowser.Api/Library/LibraryService.cs

@@ -1,1124 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Api.Movies;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Progress;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Activity;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using Microsoft.Net.Http.Headers;
-using Book = MediaBrowser.Controller.Entities.Book;
-using Episode = MediaBrowser.Controller.Entities.TV.Episode;
-using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
-using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
-using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
-using Series = MediaBrowser.Controller.Entities.TV.Series;
-
-namespace MediaBrowser.Api.Library
-{
-    [Route("/Items/{Id}/File", "GET", Summary = "Gets the original file of an item")]
-    [Authenticated]
-    public class GetFile
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetCriticReviews.
-    /// </summary>
-    [Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")]
-    [Authenticated]
-    public class GetCriticReviews : IReturn<QueryResult<BaseItemDto>>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetThemeSongs.
-    /// </summary>
-    [Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")]
-    [Authenticated]
-    public class GetThemeSongs : IReturn<ThemeMediaResult>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool InheritFromParent { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetThemeVideos.
-    /// </summary>
-    [Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")]
-    [Authenticated]
-    public class GetThemeVideos : IReturn<ThemeMediaResult>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool InheritFromParent { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetThemeVideos.
-    /// </summary>
-    [Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")]
-    [Authenticated]
-    public class GetThemeMedia : IReturn<AllThemeMediaResult>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool InheritFromParent { get; set; }
-    }
-
-    [Route("/Library/Refresh", "POST", Summary = "Starts a library scan")]
-    [Authenticated(Roles = "Admin")]
-    public class RefreshLibrary : IReturnVoid
-    {
-    }
-
-    [Route("/Items/{Id}", "DELETE", Summary = "Deletes an item from the library and file system")]
-    [Authenticated]
-    public class DeleteItem : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Items", "DELETE", Summary = "Deletes an item from the library and file system")]
-    [Authenticated]
-    public class DeleteItems : IReturnVoid
-    {
-        [ApiMember(Name = "Ids", Description = "Ids", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Ids { get; set; }
-    }
-
-    [Route("/Items/Counts", "GET")]
-    [Authenticated]
-    public class GetItemCounts : IReturn<ItemCounts>
-    {
-        [ApiMember(Name = "UserId", Description = "Optional. Get counts from a specific user's library.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "IsFavorite", Description = "Optional. Get counts of favorite items", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsFavorite { get; set; }
-    }
-
-    [Route("/Items/{Id}/Ancestors", "GET", Summary = "Gets all parents of an item")]
-    [Authenticated]
-    public class GetAncestors : IReturn<BaseItemDto[]>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetPhyscialPaths.
-    /// </summary>
-    [Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")]
-    [Authenticated(Roles = "Admin")]
-    public class GetPhyscialPaths : IReturn<List<string>>
-    {
-    }
-
-    [Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
-    [Authenticated]
-    public class GetMediaFolders : IReturn<QueryResult<BaseItemDto>>
-    {
-        [ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? IsHidden { get; set; }
-    }
-
-    [Route("/Library/Series/Added", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
-    [Route("/Library/Series/Updated", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
-    [Authenticated]
-    public class PostUpdatedSeries : IReturnVoid
-    {
-        [ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string TvdbId { get; set; }
-    }
-
-    [Route("/Library/Movies/Added", "POST", Summary = "Reports that new movies have been added by an external source")]
-    [Route("/Library/Movies/Updated", "POST", Summary = "Reports that new movies have been added by an external source")]
-    [Authenticated]
-    public class PostUpdatedMovies : IReturnVoid
-    {
-        [ApiMember(Name = "TmdbId", Description = "Tmdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string TmdbId { get; set; }
-        [ApiMember(Name = "ImdbId", Description = "Imdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string ImdbId { get; set; }
-    }
-
-    public class MediaUpdateInfo
-    {
-        public string Path { get; set; }
-
-        // Created, Modified, Deleted
-        public string UpdateType { get; set; }
-    }
-
-    [Route("/Library/Media/Updated", "POST", Summary = "Reports that new movies have been added by an external source")]
-    [Authenticated]
-    public class PostUpdatedMedia : IReturnVoid
-    {
-        [ApiMember(Name = "Updates", Description = "A list of updated media paths", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public List<MediaUpdateInfo> Updates { get; set; }
-    }
-
-    [Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
-    [Authenticated(Roles = "download")]
-    public class GetDownload
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Artists/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
-    [Route("/Items/{Id}/Similar", "GET", Summary = "Gets similar items")]
-    [Route("/Albums/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
-    [Route("/Shows/{Id}/Similar", "GET", Summary = "Finds tv shows similar to a given one.")]
-    [Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
-    [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
-    [Authenticated]
-    public class GetSimilarItems : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Route("/Libraries/AvailableOptions", "GET")]
-    [Authenticated(AllowBeforeStartupWizard = true)]
-    public class GetLibraryOptionsInfo : IReturn<LibraryOptionsResult>
-    {
-        public string LibraryContentType { get; set; }
-
-        public bool IsNewLibrary { get; set; }
-    }
-
-    public class LibraryOptionInfo
-    {
-        public string Name { get; set; }
-
-        public bool DefaultEnabled { get; set; }
-    }
-
-    public class LibraryOptionsResult
-    {
-        public LibraryOptionInfo[] MetadataSavers { get; set; }
-
-        public LibraryOptionInfo[] MetadataReaders { get; set; }
-
-        public LibraryOptionInfo[] SubtitleFetchers { get; set; }
-
-        public LibraryTypeOptions[] TypeOptions { get; set; }
-    }
-
-    public class LibraryTypeOptions
-    {
-        public string Type { get; set; }
-
-        public LibraryOptionInfo[] MetadataFetchers { get; set; }
-
-        public LibraryOptionInfo[] ImageFetchers { get; set; }
-
-        public ImageType[] SupportedImageTypes { get; set; }
-
-        public ImageOption[] DefaultImageOptions { get; set; }
-    }
-
-    /// <summary>
-    /// Class LibraryService.
-    /// </summary>
-    public class LibraryService : BaseApiService
-    {
-        private readonly IProviderManager _providerManager;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IUserManager _userManager;
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-        private readonly IActivityManager _activityManager;
-        private readonly ILocalizationManager _localization;
-        private readonly ILibraryMonitor _libraryMonitor;
-
-        private readonly ILogger<MoviesService> _moviesServiceLogger;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="LibraryService" /> class.
-        /// </summary>
-        public LibraryService(
-            ILogger<LibraryService> logger,
-            ILogger<MoviesService> moviesServiceLogger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IProviderManager providerManager,
-            ILibraryManager libraryManager,
-            IUserManager userManager,
-            IDtoService dtoService,
-            IAuthorizationContext authContext,
-            IActivityManager activityManager,
-            ILocalizationManager localization,
-            ILibraryMonitor libraryMonitor)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _providerManager = providerManager;
-            _libraryManager = libraryManager;
-            _userManager = userManager;
-            _dtoService = dtoService;
-            _authContext = authContext;
-            _activityManager = activityManager;
-            _localization = localization;
-            _libraryMonitor = libraryMonitor;
-            _moviesServiceLogger = moviesServiceLogger;
-        }
-
-        // Content Types available for each Library
-        private string[] GetRepresentativeItemTypes(string contentType)
-        {
-            return contentType switch
-            {
-                CollectionType.BoxSets => new[] {"BoxSet"},
-                CollectionType.Playlists => new[] {"Playlist"},
-                CollectionType.Movies => new[] {"Movie"},
-                CollectionType.TvShows => new[] {"Series", "Season", "Episode"},
-                CollectionType.Books => new[] {"Book"},
-                CollectionType.Music => new[] {"MusicArtist", "MusicAlbum", "Audio", "MusicVideo"},
-                CollectionType.HomeVideos => new[] {"Video", "Photo"},
-                CollectionType.Photos => new[] {"Video", "Photo"},
-                CollectionType.MusicVideos => new[] {"MusicVideo"},
-                _ => new[] {"Series", "Season", "Episode", "Movie"}
-            };
-        }
-
-        private bool IsSaverEnabledByDefault(string name, string[] itemTypes, bool isNewLibrary)
-        {
-            if (isNewLibrary)
-            {
-                return false;
-            }
-
-            var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
-                .Where(i => itemTypes.Contains(i.ItemType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
-                .ToArray();
-
-            if (metadataOptions.Length == 0)
-            {
-                return true;
-            }
-
-            return metadataOptions.Any(i => !i.DisabledMetadataSavers.Contains(name, StringComparer.OrdinalIgnoreCase));
-        }
-
-        private bool IsMetadataFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
-        {
-            if (isNewLibrary)
-            {
-                if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
-                {
-                    return !(string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
-                         || string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
-                         || string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase));
-                }
-
-                return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
-                   || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
-                   || string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
-            }
-
-            var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
-                .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
-                .ToArray();
-
-            return metadataOptions.Length == 0
-               || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase));
-        }
-
-        private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
-        {
-            if (isNewLibrary)
-            {
-                if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
-                {
-                    return !string.Equals(type, "Series", StringComparison.OrdinalIgnoreCase)
-                           && !string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
-                           && !string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
-                           && !string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase);
-                }
-
-                return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
-                       || string.Equals(name, "Screen Grabber", StringComparison.OrdinalIgnoreCase)
-                       || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
-                       || string.Equals(name, "Image Extractor", StringComparison.OrdinalIgnoreCase);
-            }
-
-            var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
-                .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
-                .ToArray();
-
-            if (metadataOptions.Length == 0)
-            {
-                return true;
-            }
-
-            return metadataOptions.Any(i => !i.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase));
-        }
-
-        public object Get(GetLibraryOptionsInfo request)
-        {
-            var result = new LibraryOptionsResult();
-
-            var types = GetRepresentativeItemTypes(request.LibraryContentType);
-            var isNewLibrary = request.IsNewLibrary;
-            var typesList = types.ToList();
-
-            var plugins = _providerManager.GetAllMetadataPlugins()
-                .Where(i => types.Contains(i.ItemType, StringComparer.OrdinalIgnoreCase))
-                .OrderBy(i => typesList.IndexOf(i.ItemType))
-                .ToList();
-
-            result.MetadataSavers = plugins
-                .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataSaver))
-                .Select(i => new LibraryOptionInfo
-                {
-                    Name = i.Name,
-                    DefaultEnabled = IsSaverEnabledByDefault(i.Name, types, isNewLibrary)
-                })
-                .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                .Select(x => x.First())
-                .ToArray();
-
-            result.MetadataReaders = plugins
-                .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.LocalMetadataProvider))
-                .Select(i => new LibraryOptionInfo
-                {
-                    Name = i.Name,
-                    DefaultEnabled = true
-                })
-                .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                .Select(x => x.First())
-                .ToArray();
-
-            result.SubtitleFetchers = plugins
-                .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.SubtitleFetcher))
-                .Select(i => new LibraryOptionInfo
-                {
-                    Name = i.Name,
-                    DefaultEnabled = true
-                })
-                .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                .Select(x => x.First())
-                .ToArray();
-
-            var typeOptions = new List<LibraryTypeOptions>();
-
-            foreach (var type in types)
-            {
-                TypeOptions.DefaultImageOptions.TryGetValue(type, out var defaultImageOptions);
-
-                typeOptions.Add(new LibraryTypeOptions
-                {
-                    Type = type,
-
-                    MetadataFetchers = plugins
-                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
-                    .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataFetcher))
-                    .Select(i => new LibraryOptionInfo
-                    {
-                        Name = i.Name,
-                        DefaultEnabled = IsMetadataFetcherEnabledByDefault(i.Name, type, isNewLibrary)
-                    })
-                    .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                    .Select(x => x.First())
-                    .ToArray(),
-
-                    ImageFetchers = plugins
-                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
-                    .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.ImageFetcher))
-                    .Select(i => new LibraryOptionInfo
-                    {
-                        Name = i.Name,
-                        DefaultEnabled = IsImageFetcherEnabledByDefault(i.Name, type, isNewLibrary)
-                    })
-                    .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                    .Select(x => x.First())
-                    .ToArray(),
-
-                    SupportedImageTypes = plugins
-                    .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
-                    .SelectMany(i => i.SupportedImageTypes ?? Array.Empty<ImageType>())
-                    .Distinct()
-                    .ToArray(),
-
-                    DefaultImageOptions = defaultImageOptions ?? Array.Empty<ImageOption>()
-                });
-            }
-
-            result.TypeOptions = typeOptions.ToArray();
-
-            return result;
-        }
-
-        public object Get(GetSimilarItems request)
-        {
-            var item = string.IsNullOrEmpty(request.Id) ?
-                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
-                _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
-            var program = item as IHasProgramAttributes;
-
-            if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
-            {
-                return new MoviesService(
-                    _moviesServiceLogger,
-                    ServerConfigurationManager,
-                    ResultFactory,
-                    _userManager,
-                    _libraryManager,
-                    _dtoService,
-                    _authContext)
-                {
-                    Request = Request,
-                }.GetSimilarItemsResult(request);
-            }
-
-            if (program != null && program.IsSeries)
-            {
-                return GetSimilarItemsResult(request, new[] { typeof(Series).Name });
-            }
-
-            if (item is Episode || (item is IItemByName && !(item is MusicArtist)))
-            {
-                return new QueryResult<BaseItemDto>();
-            }
-
-            return GetSimilarItemsResult(request, new[] { item.GetType().Name });
-        }
-
-        private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, string[] includeItemTypes)
-        {
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var item = string.IsNullOrEmpty(request.Id) ?
-                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
-                _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var query = new InternalItemsQuery(user)
-            {
-                Limit = request.Limit,
-                IncludeItemTypes = includeItemTypes,
-                SimilarTo = item,
-                DtoOptions = dtoOptions,
-                EnableTotalRecordCount = false
-            };
-
-            // ExcludeArtistIds
-            if (!string.IsNullOrEmpty(request.ExcludeArtistIds))
-            {
-                query.ExcludeArtistIds = GetGuids(request.ExcludeArtistIds);
-            }
-
-            List<BaseItem> itemsResult;
-
-            if (item is MusicArtist)
-            {
-                query.IncludeItemTypes = Array.Empty<string>();
-
-                itemsResult = _libraryManager.GetArtists(query).Items.Select(i => i.Item1).ToList();
-            }
-            else
-            {
-                itemsResult = _libraryManager.GetItemList(query);
-            }
-
-            var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = returnList,
-                TotalRecordCount = itemsResult.Count
-            };
-
-            return result;
-        }
-
-        public object Get(GetMediaFolders request)
-        {
-            var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
-
-            if (request.IsHidden.HasValue)
-            {
-                var val = request.IsHidden.Value;
-
-                items = items.Where(i => i.IsHidden == val).ToList();
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = items.Count,
-
-                Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)).ToArray()
-            };
-
-            return result;
-        }
-
-        public void Post(PostUpdatedSeries request)
-        {
-            var series = _libraryManager.GetItemList(new InternalItemsQuery
-            {
-                IncludeItemTypes = new[] { typeof(Series).Name },
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-            }).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProvider.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
-
-            foreach (var item in series)
-            {
-                _libraryMonitor.ReportFileSystemChanged(item.Path);
-            }
-        }
-
-        public void Post(PostUpdatedMedia request)
-        {
-            if (request.Updates != null)
-            {
-                foreach (var item in request.Updates)
-                {
-                    _libraryMonitor.ReportFileSystemChanged(item.Path);
-                }
-            }
-        }
-
-        public void Post(PostUpdatedMovies request)
-        {
-            var movies = _libraryManager.GetItemList(new InternalItemsQuery
-            {
-                IncludeItemTypes = new[] { typeof(Movie).Name },
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-            });
-
-            if (!string.IsNullOrWhiteSpace(request.ImdbId))
-            {
-                movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProvider.Imdb), StringComparison.OrdinalIgnoreCase)).ToList();
-            }
-            else if (!string.IsNullOrWhiteSpace(request.TmdbId))
-            {
-                movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProvider.Tmdb), StringComparison.OrdinalIgnoreCase)).ToList();
-            }
-            else
-            {
-                movies = new List<BaseItem>();
-            }
-
-            foreach (var item in movies)
-            {
-                _libraryMonitor.ReportFileSystemChanged(item.Path);
-            }
-        }
-
-        public Task<object> Get(GetDownload request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-            var auth = _authContext.GetAuthorizationInfo(Request);
-
-            var user = auth.User;
-
-            if (user != null)
-            {
-                if (!item.CanDownload(user))
-                {
-                    throw new ArgumentException("Item does not support downloading");
-                }
-            }
-            else
-            {
-                if (!item.CanDownload())
-                {
-                    throw new ArgumentException("Item does not support downloading");
-                }
-            }
-
-            var headers = new Dictionary<string, string>();
-
-            if (user != null)
-            {
-                LogDownload(item, user, auth);
-            }
-
-            var path = item.Path;
-
-            // Quotes are valid in linux. They'll possibly cause issues here
-            var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty);
-            if (!string.IsNullOrWhiteSpace(filename))
-            {
-                // Kestrel doesn't support non-ASCII characters in headers
-                if (Regex.IsMatch(filename, @"[^\p{IsBasicLatin}]"))
-                {
-                    // Manually encoding non-ASCII characters, following https://tools.ietf.org/html/rfc5987#section-3.2.2
-                    headers[HeaderNames.ContentDisposition] = "attachment; filename*=UTF-8''" + WebUtility.UrlEncode(filename);
-                }
-                else
-                {
-                    headers[HeaderNames.ContentDisposition] = "attachment; filename=\"" + filename + "\"";
-                }
-            }
-
-            return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
-            {
-                Path = path,
-                ResponseHeaders = headers
-            });
-        }
-
-        private void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
-        {
-            try
-            {
-                _activityManager.Create(new ActivityLog(
-                    string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name),
-                    "UserDownloadingContent",
-                    auth.UserId)
-                {
-                    ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
-                });
-            }
-            catch
-            {
-                // Logged at lower levels
-            }
-        }
-
-        public Task<object> Get(GetFile request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            return ResultFactory.GetStaticFileResult(Request, item.Path);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPhyscialPaths request)
-        {
-            var result = _libraryManager.RootFolder.Children
-                .SelectMany(c => c.PhysicalLocations)
-                .ToList();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetAncestors request)
-        {
-            var result = GetAncestors(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the ancestors.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto[]}.</returns>
-        public List<BaseItemDto> GetAncestors(GetAncestors request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var baseItemDtos = new List<BaseItemDto>();
-
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            BaseItem parent = item.GetParent();
-
-            while (parent != null)
-            {
-                if (user != null)
-                {
-                    parent = TranslateParentItem(parent, user);
-                }
-
-                baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
-
-                parent = parent.GetParent();
-            }
-
-            return baseItemDtos;
-        }
-
-        private BaseItem TranslateParentItem(BaseItem item, User user)
-        {
-            return item.GetParent() is AggregateFolder
-                ? _libraryManager.GetUserRootFolder().GetChildren(user, true)
-                    .FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path))
-                : item;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetCriticReviews request)
-        {
-            return new QueryResult<BaseItemDto>();
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetItemCounts request)
-        {
-            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
-            var counts = new ItemCounts
-            {
-                AlbumCount = GetCount(typeof(MusicAlbum), user, request),
-                EpisodeCount = GetCount(typeof(Episode), user, request),
-                MovieCount = GetCount(typeof(Movie), user, request),
-                SeriesCount = GetCount(typeof(Series), user, request),
-                SongCount = GetCount(typeof(Audio), user, request),
-                MusicVideoCount = GetCount(typeof(MusicVideo), user, request),
-                BoxSetCount = GetCount(typeof(BoxSet), user, request),
-                BookCount = GetCount(typeof(Book), user, request)
-            };
-
-            return ToOptimizedResult(counts);
-        }
-
-        private int GetCount(Type type, User user, GetItemCounts request)
-        {
-            var query = new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = new[] { type.Name },
-                Limit = 0,
-                Recursive = true,
-                IsVirtualItem = false,
-                IsFavorite = request.IsFavorite,
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-            };
-
-            return _libraryManager.GetItemsResult(query).TotalRecordCount;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public async Task Post(RefreshLibrary request)
-        {
-            try
-            {
-                await _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None).ConfigureAwait(false);
-            }
-            catch (Exception ex)
-            {
-                Logger.LogError(ex, "Error refreshing library");
-            }
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Delete(DeleteItems request)
-        {
-            var ids = string.IsNullOrWhiteSpace(request.Ids)
-                ? Array.Empty<string>()
-                : request.Ids.Split(',');
-
-            foreach (var i in ids)
-            {
-                var item = _libraryManager.GetItemById(i);
-                var auth = _authContext.GetAuthorizationInfo(Request);
-                var user = auth.User;
-
-                if (!item.CanDelete(user))
-                {
-                    if (ids.Length > 1)
-                    {
-                        throw new SecurityException("Unauthorized access");
-                    }
-
-                    continue;
-                }
-
-                _libraryManager.DeleteItem(item, new DeleteOptions
-                {
-                    DeleteFileLocation = true
-                }, true);
-            }
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Delete(DeleteItem request)
-        {
-            Delete(new DeleteItems
-            {
-                Ids = request.Id
-            });
-        }
-
-        public object Get(GetThemeMedia request)
-        {
-            var themeSongs = GetThemeSongs(new GetThemeSongs
-            {
-                InheritFromParent = request.InheritFromParent,
-                Id = request.Id,
-                UserId = request.UserId
-
-            });
-
-            var themeVideos = GetThemeVideos(new GetThemeVideos
-            {
-                InheritFromParent = request.InheritFromParent,
-                Id = request.Id,
-                UserId = request.UserId
-
-            });
-
-            return ToOptimizedResult(new AllThemeMediaResult
-            {
-                ThemeSongsResult = themeSongs,
-                ThemeVideosResult = themeVideos,
-
-                SoundtrackSongsResult = new ThemeMediaResult()
-            });
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetThemeSongs request)
-        {
-            var result = GetThemeSongs(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        private ThemeMediaResult GetThemeSongs(GetThemeSongs request)
-        {
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var item = string.IsNullOrEmpty(request.Id)
-                           ? (!request.UserId.Equals(Guid.Empty)
-                                  ? _libraryManager.GetUserRootFolder()
-                                  : _libraryManager.RootFolder)
-                           : _libraryManager.GetItemById(request.Id);
-
-            if (item == null)
-            {
-                throw new ResourceNotFoundException("Item not found.");
-            }
-
-            IEnumerable<BaseItem> themeItems;
-
-            while (true)
-            {
-                themeItems = item.GetThemeSongs();
-
-                if (themeItems.Any() || !request.InheritFromParent)
-                {
-                    break;
-                }
-
-                var parent = item.GetParent();
-                if (parent == null)
-                {
-                    break;
-                }
-
-                item = parent;
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-            var items = themeItems
-                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
-                .ToArray();
-
-            return new ThemeMediaResult
-            {
-                Items = items,
-                TotalRecordCount = items.Length,
-                OwnerId = item.Id
-            };
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetThemeVideos request)
-        {
-            return ToOptimizedResult(GetThemeVideos(request));
-        }
-
-        public ThemeMediaResult GetThemeVideos(GetThemeVideos request)
-        {
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var item = string.IsNullOrEmpty(request.Id)
-                           ? (!request.UserId.Equals(Guid.Empty)
-                                  ? _libraryManager.GetUserRootFolder()
-                                  : _libraryManager.RootFolder)
-                           : _libraryManager.GetItemById(request.Id);
-
-            if (item == null)
-            {
-                throw new ResourceNotFoundException("Item not found.");
-            }
-
-            IEnumerable<BaseItem> themeItems;
-
-            while (true)
-            {
-                themeItems = item.GetThemeVideos();
-
-                if (themeItems.Any() || !request.InheritFromParent)
-                {
-                    break;
-                }
-
-                var parent = item.GetParent();
-                if (parent == null)
-                {
-                    break;
-                }
-
-                item = parent;
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = themeItems
-                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
-                .ToArray();
-
-            return new ThemeMediaResult
-            {
-                Items = items,
-                TotalRecordCount = items.Length,
-                OwnerId = item.Id
-            };
-        }
-    }
-}

+ 0 - 412
MediaBrowser.Api/Library/LibraryStructureService.cs

@@ -1,412 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Progress;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Library
-{
-    /// <summary>
-    /// Class GetDefaultVirtualFolders.
-    /// </summary>
-    [Route("/Library/VirtualFolders", "GET")]
-    public class GetVirtualFolders : IReturn<List<VirtualFolderInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        public string UserId { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders", "POST")]
-    public class AddVirtualFolder : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the type of the collection.
-        /// </summary>
-        /// <value>The type of the collection.</value>
-        public string CollectionType { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [refresh library].
-        /// </summary>
-        /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
-        public bool RefreshLibrary { get; set; }
-
-        /// <summary>
-        /// Gets or sets the path.
-        /// </summary>
-        /// <value>The path.</value>
-        public string[] Paths { get; set; }
-
-        public LibraryOptions LibraryOptions { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders", "DELETE")]
-    public class RemoveVirtualFolder : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [refresh library].
-        /// </summary>
-        /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
-        public bool RefreshLibrary { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders/Name", "POST")]
-    public class RenameVirtualFolder : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string NewName { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [refresh library].
-        /// </summary>
-        /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
-        public bool RefreshLibrary { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders/Paths", "POST")]
-    public class AddMediaPath : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Path { get; set; }
-
-        public MediaPathInfo PathInfo { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [refresh library].
-        /// </summary>
-        /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
-        public bool RefreshLibrary { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders/Paths/Update", "POST")]
-    public class UpdateMediaPath : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        public MediaPathInfo PathInfo { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders/Paths", "DELETE")]
-    public class RemoveMediaPath : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Path { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [refresh library].
-        /// </summary>
-        /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
-        public bool RefreshLibrary { get; set; }
-    }
-
-    [Route("/Library/VirtualFolders/LibraryOptions", "POST")]
-    public class UpdateLibraryOptions : IReturnVoid
-    {
-        public string Id { get; set; }
-
-        public LibraryOptions LibraryOptions { get; set; }
-    }
-
-    /// <summary>
-    /// Class LibraryStructureService.
-    /// </summary>
-    [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
-    public class LibraryStructureService : BaseApiService
-    {
-        /// <summary>
-        /// The _app paths.
-        /// </summary>
-        private readonly IServerApplicationPaths _appPaths;
-
-        /// <summary>
-        /// The _library manager.
-        /// </summary>
-        private readonly ILibraryManager _libraryManager;
-        private readonly ILibraryMonitor _libraryMonitor;
-
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="LibraryStructureService" /> class.
-        /// </summary>
-        public LibraryStructureService(
-            ILogger<LibraryStructureService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ILibraryManager libraryManager,
-            ILibraryMonitor libraryMonitor)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _appPaths = serverConfigurationManager.ApplicationPaths;
-            _libraryManager = libraryManager;
-            _libraryMonitor = libraryMonitor;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetVirtualFolders request)
-        {
-            var result = _libraryManager.GetVirtualFolders(true);
-
-            return ToOptimizedResult(result);
-        }
-
-        public void Post(UpdateLibraryOptions request)
-        {
-            var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(request.Id);
-
-            collectionFolder.UpdateLibraryOptions(request.LibraryOptions);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(AddVirtualFolder request)
-        {
-            var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
-
-            if (request.Paths != null && request.Paths.Length > 0)
-            {
-                libraryOptions.PathInfos = request.Paths.Select(i => new MediaPathInfo { Path = i }).ToArray();
-            }
-
-            return _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, libraryOptions, request.RefreshLibrary);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(RenameVirtualFolder request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Name))
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            if (string.IsNullOrWhiteSpace(request.NewName))
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            var rootFolderPath = _appPaths.DefaultUserViewsPath;
-
-            var currentPath = Path.Combine(rootFolderPath, request.Name);
-            var newPath = Path.Combine(rootFolderPath, request.NewName);
-
-            if (!Directory.Exists(currentPath))
-            {
-                throw new FileNotFoundException("The media collection does not exist");
-            }
-
-            if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath))
-            {
-                throw new ArgumentException("Media library already exists at " + newPath + ".");
-            }
-
-            _libraryMonitor.Stop();
-
-            try
-            {
-                // Changing capitalization. Handle windows case insensitivity
-                if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase))
-                {
-                    var tempPath = Path.Combine(rootFolderPath, Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture));
-                    Directory.Move(currentPath, tempPath);
-                    currentPath = tempPath;
-                }
-
-                Directory.Move(currentPath, newPath);
-            }
-            finally
-            {
-                CollectionFolder.OnCollectionFolderChange();
-
-                Task.Run(() =>
-                {
-                    // No need to start if scanning the library because it will handle it
-                    if (request.RefreshLibrary)
-                    {
-                        _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
-                    }
-                    else
-                    {
-                        // Need to add a delay here or directory watchers may still pick up the changes
-                        var task = Task.Delay(1000);
-                        // Have to block here to allow exceptions to bubble
-                        Task.WaitAll(task);
-
-                        _libraryMonitor.Start();
-                    }
-                });
-            }
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Delete(RemoveVirtualFolder request)
-        {
-            return _libraryManager.RemoveVirtualFolder(request.Name, request.RefreshLibrary);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(AddMediaPath request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Name))
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            _libraryMonitor.Stop();
-
-            try
-            {
-                var mediaPath = request.PathInfo ?? new MediaPathInfo
-                {
-                    Path = request.Path
-                };
-
-                _libraryManager.AddMediaPath(request.Name, mediaPath);
-            }
-            finally
-            {
-                Task.Run(() =>
-                {
-                    // No need to start if scanning the library because it will handle it
-                    if (request.RefreshLibrary)
-                    {
-                        _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
-                    }
-                    else
-                    {
-                        // Need to add a delay here or directory watchers may still pick up the changes
-                        var task = Task.Delay(1000);
-                        // Have to block here to allow exceptions to bubble
-                        Task.WaitAll(task);
-
-                        _libraryMonitor.Start();
-                    }
-                });
-            }
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(UpdateMediaPath request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Name))
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            _libraryManager.UpdateMediaPath(request.Name, request.PathInfo);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Delete(RemoveMediaPath request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Name))
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            _libraryMonitor.Stop();
-
-            try
-            {
-                _libraryManager.RemoveMediaPath(request.Name, request.Path);
-            }
-            finally
-            {
-                Task.Run(() =>
-                {
-                    // No need to start if scanning the library because it will handle it
-                    if (request.RefreshLibrary)
-                    {
-                        _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
-                    }
-                    else
-                    {
-                        // Need to add a delay here or directory watchers may still pick up the changes
-                        var task = Task.Delay(1000);
-                        // Have to block here to allow exceptions to bubble
-                        Task.WaitAll(task);
-
-                        _libraryMonitor.Start();
-                    }
-                });
-            }
-        }
-    }
-}

+ 0 - 1287
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -1,1287 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Api.UserLibrary;
-using MediaBrowser.Common;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.LiveTv;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using Microsoft.Net.Http.Headers;
-
-namespace MediaBrowser.Api.LiveTv
-{
-    /// <summary>
-    /// This is insecure right now to avoid windows phone refactoring.
-    /// </summary>
-    [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
-    [Authenticated]
-    public class GetLiveTvInfo : IReturn<LiveTvInfo>
-    {
-    }
-
-    [Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
-    [Authenticated]
-    public class GetChannels : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        [ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public ChannelType? Type { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsMovie { get; set; }
-
-        [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSeries { get; set; }
-
-        [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsNews { get; set; }
-
-        [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsKids { get; set; }
-
-        [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSports { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "IsFavorite", Description = "Filter by channels that are favorites, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsFavorite { get; set; }
-
-        [ApiMember(Name = "IsLiked", Description = "Filter by channels that are liked, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsLiked { get; set; }
-
-        [ApiMember(Name = "IsDisliked", Description = "Filter by channels that are disliked, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsDisliked { get; set; }
-
-        [ApiMember(Name = "EnableFavoriteSorting", Description = "Incorporate favorite and like status into channel sorting.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool EnableFavoriteSorting { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool AddCurrentProgram { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public string SortBy { get; set; }
-
-        public SortOrder? SortOrder { get; set; }
-
-        /// <summary>
-        /// Gets the order by.
-        /// </summary>
-        /// <returns>IEnumerable{ItemSortBy}.</returns>
-        public string[] GetOrderBy()
-        {
-            var val = SortBy;
-
-            if (string.IsNullOrEmpty(val))
-            {
-                return Array.Empty<string>();
-            }
-
-            return val.Split(',');
-        }
-
-        public GetChannels()
-        {
-            AddCurrentProgram = true;
-        }
-    }
-
-    [Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
-    [Authenticated]
-    public class GetChannel : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    [Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
-    [Authenticated]
-    public class GetRecordings : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ChannelId { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "Status", Description = "Optional filter by recording status.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public RecordingStatus? Status { get; set; }
-
-        [ApiMember(Name = "Status", Description = "Optional filter by recordings that are in progress, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsInProgress { get; set; }
-
-        [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SeriesTimerId { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public bool? IsMovie { get; set; }
-
-        public bool? IsSeries { get; set; }
-
-        public bool? IsKids { get; set; }
-
-        public bool? IsSports { get; set; }
-
-        public bool? IsNews { get; set; }
-
-        public bool? IsLibraryItem { get; set; }
-
-        public GetRecordings()
-        {
-            EnableTotalRecordCount = true;
-        }
-    }
-
-    [Route("/LiveTv/Recordings/Series", "GET", Summary = "Gets live tv recordings")]
-    [Authenticated]
-    public class GetRecordingSeries : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ChannelId { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
-
-        [ApiMember(Name = "GroupId", Description = "Optional filter by recording group.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string GroupId { get; set; }
-
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "Status", Description = "Optional filter by recording status.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public RecordingStatus? Status { get; set; }
-
-        [ApiMember(Name = "Status", Description = "Optional filter by recordings that are in progress, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsInProgress { get; set; }
-
-        [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SeriesTimerId { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public GetRecordingSeries()
-        {
-            EnableTotalRecordCount = true;
-        }
-    }
-
-    [Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
-    [Authenticated]
-    public class GetRecordingGroups : IReturn<QueryResult<BaseItemDto>>
-    {
-        [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
-    }
-
-    [Route("/LiveTv/Recordings/Folders", "GET", Summary = "Gets recording folders")]
-    [Authenticated]
-    public class GetRecordingFolders : IReturn<BaseItemDto[]>
-    {
-        [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    [Route("/LiveTv/Recordings/{Id}", "GET", Summary = "Gets a live tv recording")]
-    [Authenticated]
-    public class GetRecording : IReturn<BaseItemDto>
-    {
-        [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    [Route("/LiveTv/Tuners/{Id}/Reset", "POST", Summary = "Resets a tv tuner")]
-    [Authenticated]
-    public class ResetTuner : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Tuner Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/Timers/{Id}", "GET", Summary = "Gets a live tv timer")]
-    [Authenticated]
-    public class GetTimer : IReturn<TimerInfoDto>
-    {
-        [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/Timers/Defaults", "GET", Summary = "Gets default values for a new timer")]
-    [Authenticated]
-    public class GetDefaultTimer : IReturn<SeriesTimerInfoDto>
-    {
-        [ApiMember(Name = "ProgramId", Description = "Optional, to attach default values based on a program.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ProgramId { get; set; }
-    }
-
-    [Route("/LiveTv/Timers", "GET", Summary = "Gets live tv timers")]
-    [Authenticated]
-    public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
-    {
-        [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ChannelId { get; set; }
-
-        [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by timers belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SeriesTimerId { get; set; }
-
-        public bool? IsActive { get; set; }
-
-        public bool? IsScheduled { get; set; }
-    }
-
-    [Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
-    [Authenticated]
-    public class GetPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        [ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string ChannelIds { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "MinStartDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string MinStartDate { get; set; }
-
-        [ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasAired { get; set; }
-
-        public bool? IsAiring { get; set; }
-
-        [ApiMember(Name = "MaxStartDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string MaxStartDate { get; set; }
-
-        [ApiMember(Name = "MinEndDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string MinEndDate { get; set; }
-
-        [ApiMember(Name = "MaxEndDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string MaxEndDate { get; set; }
-
-        [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsMovie { get; set; }
-
-        [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSeries { get; set; }
-
-        [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsNews { get; set; }
-
-        [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsKids { get; set; }
-
-        [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSports { get; set; }
-
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Name, StartDate", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string SortBy { get; set; }
-
-        [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SortOrder { get; set; }
-
-        [ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string Genres { get; set; }
-
-        [ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string GenreIds { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public string SeriesTimerId { get; set; }
-
-        public Guid LibrarySeriesId { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        public GetPrograms()
-        {
-            EnableTotalRecordCount = true;
-        }
-    }
-
-    [Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
-    [Authenticated]
-    public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        public bool EnableTotalRecordCount { get; set; }
-
-        public GetRecommendedPrograms()
-        {
-            EnableTotalRecordCount = true;
-        }
-
-        [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "IsAiring", Description = "Optional. Filter by programs that are currently airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsAiring { get; set; }
-
-        [ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasAired { get; set; }
-
-        [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSeries { get; set; }
-
-        [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsMovie { get; set; }
-
-        [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsNews { get; set; }
-
-        [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsKids { get; set; }
-
-        [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSports { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string GenreIds { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-    }
-
-    [Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
-    [Authenticated]
-    public class GetProgram : IReturn<BaseItemDto>
-    {
-        [ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-
-    [Route("/LiveTv/Recordings/{Id}", "DELETE", Summary = "Deletes a live tv recording")]
-    [Authenticated]
-    public class DeleteRecording : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-    }
-
-    [Route("/LiveTv/Timers/{Id}", "DELETE", Summary = "Cancels a live tv timer")]
-    [Authenticated]
-    public class CancelTimer : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/Timers/{Id}", "POST", Summary = "Updates a live tv timer")]
-    [Authenticated]
-    public class UpdateTimer : TimerInfoDto, IReturnVoid
-    {
-    }
-
-    [Route("/LiveTv/Timers", "POST", Summary = "Creates a live tv timer")]
-    [Authenticated]
-    public class CreateTimer : TimerInfoDto, IReturnVoid
-    {
-    }
-
-    [Route("/LiveTv/SeriesTimers/{Id}", "GET", Summary = "Gets a live tv series timer")]
-    [Authenticated]
-    public class GetSeriesTimer : IReturn<TimerInfoDto>
-    {
-        [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/SeriesTimers", "GET", Summary = "Gets live tv series timers")]
-    [Authenticated]
-    public class GetSeriesTimers : IReturn<QueryResult<SeriesTimerInfoDto>>
-    {
-        [ApiMember(Name = "SortBy", Description = "Optional. Sort by SortName or Priority", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string SortBy { get; set; }
-
-        [ApiMember(Name = "SortOrder", Description = "Optional. Sort in Ascending or Descending order", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public SortOrder SortOrder { get; set; }
-    }
-
-    [Route("/LiveTv/SeriesTimers/{Id}", "DELETE", Summary = "Cancels a live tv series timer")]
-    [Authenticated]
-    public class CancelSeriesTimer : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/SeriesTimers/{Id}", "POST", Summary = "Updates a live tv series timer")]
-    [Authenticated]
-    public class UpdateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
-    {
-    }
-
-    [Route("/LiveTv/SeriesTimers", "POST", Summary = "Creates a live tv series timer")]
-    [Authenticated]
-    public class CreateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
-    {
-    }
-
-    [Route("/LiveTv/Recordings/Groups/{Id}", "GET", Summary = "Gets a recording group")]
-    [Authenticated]
-    public class GetRecordingGroup : IReturn<BaseItemDto>
-    {
-        [ApiMember(Name = "Id", Description = "Recording group Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/GuideInfo", "GET", Summary = "Gets guide info")]
-    [Authenticated]
-    public class GetGuideInfo : IReturn<GuideInfo>
-    {
-    }
-
-    [Route("/LiveTv/TunerHosts", "POST", Summary = "Adds a tuner host")]
-    [Authenticated]
-    public class AddTunerHost : TunerHostInfo, IReturn<TunerHostInfo>
-    {
-    }
-
-    [Route("/LiveTv/TunerHosts", "DELETE", Summary = "Deletes a tuner host")]
-    [Authenticated]
-    public class DeleteTunerHost : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Tuner host id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/ListingProviders/Default", "GET")]
-    [Authenticated]
-    public class GetDefaultListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
-    {
-    }
-
-    [Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
-    [Authenticated]
-    public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
-    {
-        public bool ValidateLogin { get; set; }
-
-        public bool ValidateListings { get; set; }
-
-        public string Pw { get; set; }
-    }
-
-    [Route("/LiveTv/ListingProviders", "DELETE", Summary = "Deletes a listing provider")]
-    [Authenticated]
-    public class DeleteListingProvider : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/ListingProviders/Lineups", "GET", Summary = "Gets available lineups")]
-    [Authenticated]
-    public class GetLineups : IReturn<List<NameIdPair>>
-    {
-        [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "Type", Description = "Provider Type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Type { get; set; }
-
-        [ApiMember(Name = "Location", Description = "Location", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Location { get; set; }
-
-        [ApiMember(Name = "Country", Description = "Country", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Country { get; set; }
-    }
-
-    [Route("/LiveTv/ListingProviders/SchedulesDirect/Countries", "GET", Summary = "Gets available lineups")]
-    [Authenticated]
-    public class GetSchedulesDirectCountries
-    {
-    }
-
-    [Route("/LiveTv/ChannelMappingOptions")]
-    [Authenticated]
-    public class GetChannelMappingOptions
-    {
-        [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query")]
-        public string ProviderId { get; set; }
-    }
-
-    [Route("/LiveTv/ChannelMappings")]
-    [Authenticated]
-    public class SetChannelMapping
-    {
-        [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query")]
-        public string ProviderId { get; set; }
-
-        public string TunerChannelId { get; set; }
-
-        public string ProviderChannelId { get; set; }
-    }
-
-    public class ChannelMappingOptions
-    {
-        public List<TunerChannelMapping> TunerChannels { get; set; }
-
-        public List<NameIdPair> ProviderChannels { get; set; }
-
-        public NameValuePair[] Mappings { get; set; }
-
-        public string ProviderName { get; set; }
-    }
-
-    [Route("/LiveTv/LiveStreamFiles/{Id}/stream.{Container}", "GET", Summary = "Gets a live tv channel")]
-    public class GetLiveStreamFile
-    {
-        public string Id { get; set; }
-
-        public string Container { get; set; }
-    }
-
-    [Route("/LiveTv/LiveRecordings/{Id}/stream", "GET", Summary = "Gets a live tv channel")]
-    public class GetLiveRecordingFile
-    {
-        public string Id { get; set; }
-    }
-
-    [Route("/LiveTv/TunerHosts/Types", "GET")]
-    [Authenticated]
-    public class GetTunerHostTypes : IReturn<List<NameIdPair>>
-    {
-    }
-
-    [Route("/LiveTv/Tuners/Discvover", "GET")]
-    [Authenticated]
-    public class DiscoverTuners : IReturn<List<TunerHostInfo>>
-    {
-        public bool NewDevicesOnly { get; set; }
-    }
-
-    public class LiveTvService : BaseApiService
-    {
-        private readonly ILiveTvManager _liveTvManager;
-        private readonly IUserManager _userManager;
-        private readonly IHttpClient _httpClient;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-        private readonly ISessionContext _sessionContext;
-        private readonly IStreamHelper _streamHelper;
-        private readonly IMediaSourceManager _mediaSourceManager;
-
-        public LiveTvService(
-            ILogger<LiveTvService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IMediaSourceManager mediaSourceManager,
-            IStreamHelper streamHelper,
-            ILiveTvManager liveTvManager,
-            IUserManager userManager,
-            IHttpClient httpClient,
-            ILibraryManager libraryManager,
-            IDtoService dtoService,
-            IAuthorizationContext authContext,
-            ISessionContext sessionContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _mediaSourceManager = mediaSourceManager;
-            _streamHelper = streamHelper;
-            _liveTvManager = liveTvManager;
-            _userManager = userManager;
-            _httpClient = httpClient;
-            _libraryManager = libraryManager;
-            _dtoService = dtoService;
-            _authContext = authContext;
-            _sessionContext = sessionContext;
-        }
-
-        public object Get(GetTunerHostTypes request)
-        {
-            var list = _liveTvManager.GetTunerHostTypes();
-            return ToOptimizedResult(list);
-        }
-
-        public object Get(GetRecordingFolders request)
-        {
-            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-            var folders = _liveTvManager.GetRecordingFolders(user);
-
-            var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = returnArray,
-                TotalRecordCount = returnArray.Count
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetLiveRecordingFile request)
-        {
-            var path = _liveTvManager.GetEmbyTvActiveRecordingPath(request.Id);
-
-            if (string.IsNullOrWhiteSpace(path))
-            {
-                throw new FileNotFoundException();
-            }
-
-            var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
-            {
-                [HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType(path)
-            };
-
-            return new ProgressiveFileCopier(_streamHelper, path, outputHeaders, Logger)
-            {
-                AllowEndOfFile = false
-            };
-        }
-
-        public async Task<object> Get(DiscoverTuners request)
-        {
-            var result = await _liveTvManager.DiscoverTuners(request.NewDevicesOnly, CancellationToken.None).ConfigureAwait(false);
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetLiveStreamFile request)
-        {
-            var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(request.Id, CancellationToken.None).ConfigureAwait(false);
-
-            var directStreamProvider = liveStreamInfo;
-
-            var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
-            {
-                [HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType("file." + request.Container)
-            };
-
-            return new ProgressiveFileCopier(directStreamProvider, _streamHelper, outputHeaders, Logger)
-            {
-                AllowEndOfFile = false
-            };
-        }
-
-        public object Get(GetDefaultListingProvider request)
-        {
-            return ToOptimizedResult(new ListingsProviderInfo());
-        }
-
-        public async Task<object> Post(SetChannelMapping request)
-        {
-            return await _liveTvManager.SetChannelMapping(request.ProviderId, request.TunerChannelId, request.ProviderChannelId).ConfigureAwait(false);
-        }
-
-        public async Task<object> Get(GetChannelMappingOptions request)
-        {
-            var config = GetConfiguration();
-
-            var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
-
-            var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name;
-
-            var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
-                        .ConfigureAwait(false);
-
-            var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
-                     .ConfigureAwait(false);
-
-            var mappings = listingsProviderInfo.ChannelMappings;
-
-            var result = new ChannelMappingOptions
-            {
-                TunerChannels = tunerChannels.Select(i => _liveTvManager.GetTunerChannelMapping(i, mappings, providerChannels)).ToList(),
-
-                ProviderChannels = providerChannels.Select(i => new NameIdPair
-                {
-                    Name = i.Name,
-                    Id = i.Id
-                }).ToList(),
-
-                Mappings = mappings,
-
-                ProviderName = listingsProviderName
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetSchedulesDirectCountries request)
-        {
-            // https://json.schedulesdirect.org/20141201/available/countries
-
-            var response = await _httpClient.Get(new HttpRequestOptions
-            {
-                Url = "https://json.schedulesdirect.org/20141201/available/countries",
-                BufferContent = false
-            }).ConfigureAwait(false);
-
-            return ResultFactory.GetResult(Request, response, "application/json");
-        }
-
-        private void AssertUserCanManageLiveTv()
-        {
-            var user = _sessionContext.GetUser(Request);
-
-            if (user == null)
-            {
-                throw new SecurityException("Anonymous live tv management is not allowed.");
-            }
-
-            if (!user.HasPermission(PermissionKind.EnableLiveTvManagement))
-            {
-                throw new SecurityException("The current user does not have permission to manage live tv.");
-            }
-        }
-
-        public async Task<object> Post(AddListingProvider request)
-        {
-            if (request.Pw != null)
-            {
-                request.Password = GetHashedString(request.Pw);
-            }
-
-            request.Pw = null;
-
-            var result = await _liveTvManager.SaveListingProvider(request, request.ValidateLogin, request.ValidateListings).ConfigureAwait(false);
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the hashed string.
-        /// </summary>
-        private string GetHashedString(string str)
-        {
-            // SchedulesDirect requires a SHA1 hash of the user's password
-            // https://github.com/SchedulesDirect/JSON-Service/wiki/API-20141201#obtain-a-token
-            using SHA1 sha = SHA1.Create();
-
-            return Hex.Encode(
-                sha.ComputeHash(Encoding.UTF8.GetBytes(str)));
-        }
-
-        public void Delete(DeleteListingProvider request)
-        {
-            _liveTvManager.DeleteListingsProvider(request.Id);
-        }
-
-        public async Task<object> Post(AddTunerHost request)
-        {
-            var result = await _liveTvManager.SaveTunerHost(request).ConfigureAwait(false);
-            return ToOptimizedResult(result);
-        }
-
-        public void Delete(DeleteTunerHost request)
-        {
-            var config = GetConfiguration();
-
-            config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
-
-            ServerConfigurationManager.SaveConfiguration("livetv", config);
-        }
-
-        private LiveTvOptions GetConfiguration()
-        {
-            return ServerConfigurationManager.GetConfiguration<LiveTvOptions>("livetv");
-        }
-
-        private void UpdateConfiguration(LiveTvOptions options)
-        {
-            ServerConfigurationManager.SaveConfiguration("livetv", options);
-        }
-
-        public async Task<object> Get(GetLineups request)
-        {
-            var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
-
-            return ToOptimizedResult(info);
-        }
-
-        public object Get(GetLiveTvInfo request)
-        {
-            var info = _liveTvManager.GetLiveTvInfo(CancellationToken.None);
-
-            return ToOptimizedResult(info);
-        }
-
-        public object Get(GetChannels request)
-        {
-            var options = GetDtoOptions(_authContext, request);
-
-            var channelResult = _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
-            {
-                ChannelType = request.Type,
-                UserId = request.UserId,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                IsFavorite = request.IsFavorite,
-                IsLiked = request.IsLiked,
-                IsDisliked = request.IsDisliked,
-                EnableFavoriteSorting = request.EnableFavoriteSorting,
-                IsMovie = request.IsMovie,
-                IsSeries = request.IsSeries,
-                IsNews = request.IsNews,
-                IsKids = request.IsKids,
-                IsSports = request.IsSports,
-                SortBy = request.GetOrderBy(),
-                SortOrder = request.SortOrder ?? SortOrder.Ascending,
-                AddCurrentProgram = request.AddCurrentProgram
-            }, options, CancellationToken.None);
-
-            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
-            RemoveFields(options);
-
-            options.AddCurrentProgram = request.AddCurrentProgram;
-
-            var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, options, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = returnArray,
-                TotalRecordCount = channelResult.TotalRecordCount
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        private void RemoveFields(DtoOptions options)
-        {
-            var fields = options.Fields.ToList();
-
-            fields.Remove(ItemFields.CanDelete);
-            fields.Remove(ItemFields.CanDownload);
-            fields.Remove(ItemFields.DisplayPreferencesId);
-            fields.Remove(ItemFields.Etag);
-            options.Fields = fields.ToArray();
-        }
-
-        public object Get(GetChannel request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetPrograms request)
-        {
-            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
-            var query = new InternalItemsQuery(user)
-            {
-                ChannelIds = ApiEntryPoint.Split(request.ChannelIds, ',', true).Select(i => new Guid(i)).ToArray(),
-                HasAired = request.HasAired,
-                IsAiring = request.IsAiring,
-                EnableTotalRecordCount = request.EnableTotalRecordCount
-            };
-
-            if (!string.IsNullOrEmpty(request.MinStartDate))
-            {
-                query.MinStartDate = DateTime.Parse(request.MinStartDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MinEndDate))
-            {
-                query.MinEndDate = DateTime.Parse(request.MinEndDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MaxStartDate))
-            {
-                query.MaxStartDate = DateTime.Parse(request.MaxStartDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MaxEndDate))
-            {
-                query.MaxEndDate = DateTime.Parse(request.MaxEndDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            query.StartIndex = request.StartIndex;
-            query.Limit = request.Limit;
-            query.OrderBy = BaseItemsRequest.GetOrderBy(request.SortBy, request.SortOrder);
-            query.IsNews = request.IsNews;
-            query.IsMovie = request.IsMovie;
-            query.IsSeries = request.IsSeries;
-            query.IsKids = request.IsKids;
-            query.IsSports = request.IsSports;
-            query.SeriesTimerId = request.SeriesTimerId;
-            query.Genres = (request.Genres ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-            query.GenreIds = GetGuids(request.GenreIds);
-
-            if (!request.LibrarySeriesId.Equals(Guid.Empty))
-            {
-                query.IsSeries = true;
-
-                if (_libraryManager.GetItemById(request.LibrarySeriesId) is Series series)
-                {
-                    query.Name = series.Name;
-                }
-            }
-
-            var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetRecommendedPrograms request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var query = new InternalItemsQuery(user)
-            {
-                IsAiring = request.IsAiring,
-                Limit = request.Limit,
-                HasAired = request.HasAired,
-                IsSeries = request.IsSeries,
-                IsMovie = request.IsMovie,
-                IsKids = request.IsKids,
-                IsNews = request.IsNews,
-                IsSports = request.IsSports,
-                EnableTotalRecordCount = request.EnableTotalRecordCount
-            };
-
-            query.GenreIds = GetGuids(request.GenreIds);
-
-            var result = _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None);
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Post(GetPrograms request)
-        {
-            return Get(request);
-        }
-
-        public object Get(GetRecordings request)
-        {
-            var options = GetDtoOptions(_authContext, request);
-
-            var result = _liveTvManager.GetRecordings(new RecordingQuery
-            {
-                ChannelId = request.ChannelId,
-                UserId = request.UserId,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                Status = request.Status,
-                SeriesTimerId = request.SeriesTimerId,
-                IsInProgress = request.IsInProgress,
-                EnableTotalRecordCount = request.EnableTotalRecordCount,
-                IsMovie = request.IsMovie,
-                IsNews = request.IsNews,
-                IsSeries = request.IsSeries,
-                IsKids = request.IsKids,
-                IsSports = request.IsSports,
-                IsLibraryItem = request.IsLibraryItem,
-                Fields = request.GetItemFields(),
-                ImageTypeLimit = request.ImageTypeLimit,
-                EnableImages = request.EnableImages
-            }, options);
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetRecordingSeries request)
-        {
-            return ToOptimizedResult(new QueryResult<BaseItemDto>());
-        }
-
-        public object Get(GetRecording request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetTimer request)
-        {
-            var result = await _liveTvManager.GetTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetTimers request)
-        {
-            var result = await _liveTvManager.GetTimers(new TimerQuery
-            {
-                ChannelId = request.ChannelId,
-                SeriesTimerId = request.SeriesTimerId,
-                IsActive = request.IsActive,
-                IsScheduled = request.IsScheduled
-            }, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public void Delete(DeleteRecording request)
-        {
-            AssertUserCanManageLiveTv();
-
-            _libraryManager.DeleteItem(_libraryManager.GetItemById(request.Id), new DeleteOptions
-            {
-                DeleteFileLocation = false
-            });
-        }
-
-        public Task Delete(CancelTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.CancelTimer(request.Id);
-        }
-
-        public Task Post(UpdateTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.UpdateTimer(request, CancellationToken.None);
-        }
-
-        public async Task<object> Get(GetSeriesTimers request)
-        {
-            var result = await _liveTvManager.GetSeriesTimers(new SeriesTimerQuery
-            {
-                SortOrder = request.SortOrder,
-                SortBy = request.SortBy
-            }, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetSeriesTimer request)
-        {
-            var result = await _liveTvManager.GetSeriesTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public Task Delete(CancelSeriesTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.CancelSeriesTimer(request.Id);
-        }
-
-        public Task Post(UpdateSeriesTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.UpdateSeriesTimer(request, CancellationToken.None);
-        }
-
-        public async Task<object> Get(GetDefaultTimer request)
-        {
-            if (string.IsNullOrEmpty(request.ProgramId))
-            {
-                var result = await _liveTvManager.GetNewTimerDefaults(CancellationToken.None).ConfigureAwait(false);
-
-                return ToOptimizedResult(result);
-            }
-            else
-            {
-                var result = await _liveTvManager.GetNewTimerDefaults(request.ProgramId, CancellationToken.None).ConfigureAwait(false);
-
-                return ToOptimizedResult(result);
-            }
-        }
-
-        public async Task<object> Get(GetProgram request)
-        {
-            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
-            var result = await _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public Task Post(CreateSeriesTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.CreateSeriesTimer(request, CancellationToken.None);
-        }
-
-        public Task Post(CreateTimer request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.CreateTimer(request, CancellationToken.None);
-        }
-
-        public object Get(GetRecordingGroups request)
-        {
-            return ToOptimizedResult(new QueryResult<BaseItemDto>());
-        }
-
-        public object Get(GetRecordingGroup request)
-        {
-            throw new FileNotFoundException();
-        }
-
-        public object Get(GetGuideInfo request)
-        {
-            return ToOptimizedResult(_liveTvManager.GetGuideInfo());
-        }
-
-        public Task Post(ResetTuner request)
-        {
-            AssertUserCanManageLiveTv();
-
-            return _liveTvManager.ResetTuner(request.Id, CancellationToken.None);
-        }
-    }
-}

+ 0 - 111
MediaBrowser.Api/LocalizationService.cs

@@ -1,111 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetCultures.
-    /// </summary>
-    [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
-    public class GetCultures : IReturn<CultureDto[]>
-    {
-    }
-
-    /// <summary>
-    /// Class GetCountries.
-    /// </summary>
-    [Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
-    public class GetCountries : IReturn<CountryInfo[]>
-    {
-    }
-
-    /// <summary>
-    /// Class ParentalRatings.
-    /// </summary>
-    [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
-    public class GetParentalRatings : IReturn<ParentalRating[]>
-    {
-    }
-
-    /// <summary>
-    /// Class ParentalRatings.
-    /// </summary>
-    [Route("/Localization/Options", "GET", Summary = "Gets localization options")]
-    public class GetLocalizationOptions : IReturn<LocalizationOption[]>
-    {
-    }
-
-    /// <summary>
-    /// Class CulturesService.
-    /// </summary>
-    [Authenticated(AllowBeforeStartupWizard = true)]
-    public class LocalizationService : BaseApiService
-    {
-        /// <summary>
-        /// The _localization.
-        /// </summary>
-        private readonly ILocalizationManager _localization;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="LocalizationService"/> class.
-        /// </summary>
-        /// <param name="localization">The localization.</param>
-        public LocalizationService(
-            ILogger<LocalizationService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ILocalizationManager localization)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _localization = localization;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetParentalRatings request)
-        {
-            var result = _localization.GetParentalRatings();
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetLocalizationOptions request)
-        {
-            var result = _localization.GetLocalizationOptions();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetCountries request)
-        {
-            var result = _localization.GetCountries();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetCultures request)
-        {
-            var result = _localization.GetCultures();
-
-            return ToOptimizedResult(result);
-        }
-    }
-
-}

+ 0 - 104
MediaBrowser.Api/Movies/CollectionService.cs

@@ -1,104 +0,0 @@
-using System;
-using MediaBrowser.Controller.Collections;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Collections;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Movies
-{
-    [Route("/Collections", "POST", Summary = "Creates a new collection")]
-    public class CreateCollection : IReturn<CollectionCreationResult>
-    {
-        [ApiMember(Name = "IsLocked", Description = "Whether or not to lock the new collection.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
-        public bool IsLocked { get; set; }
-
-        [ApiMember(Name = "Name", Description = "The name of the new collection.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Name { get; set; }
-
-        [ApiMember(Name = "ParentId", Description = "Optional - create the collection within a specific folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "Ids", Description = "Item Ids to add to the collection", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
-        public string Ids { get; set; }
-    }
-
-    [Route("/Collections/{Id}/Items", "POST", Summary = "Adds items to a collection")]
-    public class AddToCollection : IReturnVoid
-    {
-        [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Ids { get; set; }
-
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Collections/{Id}/Items", "DELETE", Summary = "Removes items from a collection")]
-    public class RemoveFromCollection : IReturnVoid
-    {
-        [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string Ids { get; set; }
-
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Authenticated]
-    public class CollectionService : BaseApiService
-    {
-        private readonly ICollectionManager _collectionManager;
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-
-        public CollectionService(
-            ILogger<CollectionService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ICollectionManager collectionManager,
-            IDtoService dtoService,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _collectionManager = collectionManager;
-            _dtoService = dtoService;
-            _authContext = authContext;
-        }
-
-        public object Post(CreateCollection request)
-        {
-            var userId = _authContext.GetAuthorizationInfo(Request).UserId;
-
-            var parentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
-
-            var item = _collectionManager.CreateCollection(new CollectionCreationOptions
-            {
-                IsLocked = request.IsLocked,
-                Name = request.Name,
-                ParentId = parentId,
-                ItemIdList = SplitValue(request.Ids, ','),
-                UserIds = new[] { userId }
-            });
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
-
-            return new CollectionCreationResult
-            {
-                Id = dto.Id
-            };
-        }
-
-        public void Post(AddToCollection request)
-        {
-            _collectionManager.AddToCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
-        }
-
-        public void Delete(RemoveFromCollection request)
-        {
-            _collectionManager.RemoveFromCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
-        }
-    }
-}

+ 0 - 414
MediaBrowser.Api/Movies/MoviesService.cs

@@ -1,414 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
-using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
-
-namespace MediaBrowser.Api.Movies
-{
-    [Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
-    public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasDtoOptions
-    {
-        [ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int CategoryLimit { get; set; }
-
-        [ApiMember(Name = "ItemLimit", Description = "The max number of items to return per category", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int ItemLimit { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Specify this to localize the search to a specific item or folder. Omit to use the root.
-        /// </summary>
-        /// <value>The parent id.</value>
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        public GetMovieRecommendations()
-        {
-            CategoryLimit = 5;
-            ItemLimit = 8;
-        }
-
-        public string Fields { get; set; }
-    }
-
-    /// <summary>
-    /// Class MoviesService.
-    /// </summary>
-    [Authenticated]
-    public class MoviesService : BaseApiService
-    {
-        /// <summary>
-        /// The _user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-
-        private readonly ILibraryManager _libraryManager;
-
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MoviesService" /> class.
-        /// </summary>
-        public MoviesService(
-            ILogger<MoviesService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IDtoService dtoService,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _dtoService = dtoService;
-            _authContext = authContext;
-        }
-
-        public object Get(GetMovieRecommendations request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = GetRecommendationCategories(user, request.ParentId, request.CategoryLimit, request.ItemLimit, dtoOptions);
-
-            return ToOptimizedResult(result);
-        }
-
-        public QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
-        {
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var item = string.IsNullOrEmpty(request.Id) ?
-                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
-                _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
-            var itemTypes = new List<string> { typeof(Movie).Name };
-            if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
-            {
-                itemTypes.Add(typeof(Trailer).Name);
-                itemTypes.Add(typeof(LiveTvProgram).Name);
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
-            {
-                Limit = request.Limit,
-                IncludeItemTypes = itemTypes.ToArray(),
-                IsMovie = true,
-                SimilarTo = item,
-                EnableGroupByMetadataKey = true,
-                DtoOptions = dtoOptions
-
-            });
-
-            var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = returnList,
-
-                TotalRecordCount = itemsResult.Count
-            };
-
-            return result;
-        }
-
-        private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
-        {
-            var categories = new List<RecommendationDto>();
-
-            var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? Guid.Empty : new Guid(parentId);
-
-            var query = new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = new[]
-                {
-                    typeof(Movie).Name,
-                    // typeof(Trailer).Name,
-                    // typeof(LiveTvProgram).Name
-                },
-                // IsMovie = true
-                OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
-                Limit = 7,
-                ParentId = parentIdGuid,
-                Recursive = true,
-                IsPlayed = true,
-                DtoOptions = dtoOptions
-            };
-
-            var recentlyPlayedMovies = _libraryManager.GetItemList(query);
-
-            var itemTypes = new List<string> { typeof(Movie).Name };
-            if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
-            {
-                itemTypes.Add(typeof(Trailer).Name);
-                itemTypes.Add(typeof(LiveTvProgram).Name);
-            }
-
-            var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = itemTypes.ToArray(),
-                IsMovie = true,
-                OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
-                Limit = 10,
-                IsFavoriteOrLiked = true,
-                ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(),
-                EnableGroupByMetadataKey = true,
-                ParentId = parentIdGuid,
-                Recursive = true,
-                DtoOptions = dtoOptions
-            });
-
-            var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
-            // Get recently played directors
-            var recentDirectors = GetDirectors(mostRecentMovies)
-                .ToList();
-
-            // Get recently played actors
-            var recentActors = GetActors(mostRecentMovies)
-                .ToList();
-
-            var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
-            var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
-
-            var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
-            var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
-
-            var categoryTypes = new List<IEnumerator<RecommendationDto>>
-            {
-                // Give this extra weight
-                similarToRecentlyPlayed,
-                similarToRecentlyPlayed,
-
-                // Give this extra weight
-                similarToLiked,
-                similarToLiked,
-
-                hasDirectorFromRecentlyPlayed,
-                hasActorFromRecentlyPlayed
-            };
-
-            while (categories.Count < categoryLimit)
-            {
-                var allEmpty = true;
-
-                foreach (var category in categoryTypes)
-                {
-                    if (category.MoveNext())
-                    {
-                        categories.Add(category.Current);
-                        allEmpty = false;
-
-                        if (categories.Count >= categoryLimit)
-                        {
-                            break;
-                        }
-                    }
-                }
-
-                if (allEmpty)
-                {
-                    break;
-                }
-            }
-
-            return categories.OrderBy(i => i.RecommendationType);
-        }
-
-        private IEnumerable<RecommendationDto> GetWithDirector(
-            User user,
-            IEnumerable<string> names,
-            int itemLimit,
-            DtoOptions dtoOptions,
-            RecommendationType type)
-        {
-            var itemTypes = new List<string> { typeof(Movie).Name };
-            if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
-            {
-                itemTypes.Add(typeof(Trailer).Name);
-                itemTypes.Add(typeof(LiveTvProgram).Name);
-            }
-
-            foreach (var name in names)
-            {
-                var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
-                {
-                    Person = name,
-                    // Account for duplicates by imdb id, since the database doesn't support this yet
-                    Limit = itemLimit + 2,
-                    PersonTypes = new[] { PersonType.Director },
-                    IncludeItemTypes = itemTypes.ToArray(),
-                    IsMovie = true,
-                    EnableGroupByMetadataKey = true,
-                    DtoOptions = dtoOptions
-                }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
-                .Select(x => x.First())
-                .Take(itemLimit)
-                .ToList();
-
-                if (items.Count > 0)
-                {
-                    var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
-
-                    yield return new RecommendationDto
-                    {
-                        BaselineItemName = name,
-                        CategoryId = name.GetMD5(),
-                        RecommendationType = type,
-                        Items = returnItems
-                    };
-                }
-            }
-        }
-
-        private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
-        {
-            var itemTypes = new List<string> { typeof(Movie).Name };
-            if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
-            {
-                itemTypes.Add(typeof(Trailer).Name);
-                itemTypes.Add(typeof(LiveTvProgram).Name);
-            }
-
-            foreach (var name in names)
-            {
-                var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
-                {
-                    Person = name,
-                    // Account for duplicates by imdb id, since the database doesn't support this yet
-                    Limit = itemLimit + 2,
-                    IncludeItemTypes = itemTypes.ToArray(),
-                    IsMovie = true,
-                    EnableGroupByMetadataKey = true,
-                    DtoOptions = dtoOptions
-                }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
-                .Select(x => x.First())
-                .Take(itemLimit)
-                .ToList();
-
-                if (items.Count > 0)
-                {
-                    var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
-
-                    yield return new RecommendationDto
-                    {
-                        BaselineItemName = name,
-                        CategoryId = name.GetMD5(),
-                        RecommendationType = type,
-                        Items = returnItems
-                    };
-                }
-            }
-        }
-
-        private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
-        {
-            var itemTypes = new List<string> { typeof(Movie).Name };
-            if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
-            {
-                itemTypes.Add(typeof(Trailer).Name);
-                itemTypes.Add(typeof(LiveTvProgram).Name);
-            }
-
-            foreach (var item in baselineItems)
-            {
-                var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
-                {
-                    Limit = itemLimit,
-                    IncludeItemTypes = itemTypes.ToArray(),
-                    IsMovie = true,
-                    SimilarTo = item,
-                    EnableGroupByMetadataKey = true,
-                    DtoOptions = dtoOptions
-                });
-
-                if (similar.Count > 0)
-                {
-                    var returnItems = _dtoService.GetBaseItemDtos(similar, dtoOptions, user);
-
-                    yield return new RecommendationDto
-                    {
-                        BaselineItemName = item.Name,
-                        CategoryId = item.Id,
-                        RecommendationType = type,
-                        Items = returnItems
-                    };
-                }
-            }
-        }
-
-        private IEnumerable<string> GetActors(List<BaseItem> items)
-        {
-            var people = _libraryManager.GetPeople(new InternalPeopleQuery
-            {
-                ExcludePersonTypes = new[]
-                {
-                    PersonType.Director
-                },
-                MaxListOrder = 3
-            });
-
-            var itemIds = items.Select(i => i.Id).ToList();
-
-            return people
-                .Where(i => itemIds.Contains(i.ItemId))
-                .Select(i => i.Name)
-                .DistinctNames();
-        }
-
-        private IEnumerable<string> GetDirectors(List<BaseItem> items)
-        {
-            var people = _libraryManager.GetPeople(new InternalPeopleQuery
-            {
-                PersonTypes = new[]
-                {
-                    PersonType.Director
-                }
-            });
-
-            var itemIds = items.Select(i => i.Id).ToList();
-
-            return people
-                .Where(i => itemIds.Contains(i.ItemId))
-                .Select(i => i.Name)
-                .DistinctNames();
-        }
-    }
-}

+ 0 - 88
MediaBrowser.Api/Movies/TrailersService.cs

@@ -1,88 +0,0 @@
-using MediaBrowser.Api.UserLibrary;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Movies
-{
-    [Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
-    public class Getrailers : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
-    {
-    }
-
-    /// <summary>
-    /// Class TrailersService.
-    /// </summary>
-    [Authenticated]
-    public class TrailersService : BaseApiService
-    {
-        /// <summary>
-        /// The _user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-
-        /// <summary>
-        /// The _library manager.
-        /// </summary>
-        private readonly ILibraryManager _libraryManager;
-
-        /// <summary>
-        /// The logger for the created <see cref="ItemsService"/> instances.
-        /// </summary>
-        private readonly ILogger<ItemsService> _logger;
-
-        private readonly IDtoService _dtoService;
-        private readonly ILocalizationManager _localizationManager;
-        private readonly IJsonSerializer _json;
-        private readonly IAuthorizationContext _authContext;
-
-        public TrailersService(
-            ILoggerFactory loggerFactory,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IDtoService dtoService,
-            ILocalizationManager localizationManager,
-            IJsonSerializer json,
-            IAuthorizationContext authContext)
-            : base(loggerFactory.CreateLogger<TrailersService>(), serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _dtoService = dtoService;
-            _localizationManager = localizationManager;
-            _json = json;
-            _authContext = authContext;
-            _logger = loggerFactory.CreateLogger<ItemsService>();
-        }
-
-        public object Get(Getrailers request)
-        {
-            var json = _json.SerializeToString(request);
-            var getItems = _json.DeserializeFromString<GetItems>(json);
-
-            getItems.IncludeItemTypes = "Trailer";
-
-            return new ItemsService(
-                _logger,
-                ServerConfigurationManager,
-                ResultFactory,
-                _userManager,
-                _libraryManager,
-                _localizationManager,
-                _dtoService,
-                _authContext)
-            {
-                Request = Request,
-            }.Get(getItems);
-        }
-    }
-}

+ 0 - 132
MediaBrowser.Api/Music/AlbumsService.cs

@@ -1,132 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Music
-{
-    [Route("/Albums/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
-    public class GetSimilarAlbums : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Route("/Artists/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
-    public class GetSimilarArtists : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Authenticated]
-    public class AlbumsService : BaseApiService
-    {
-        /// <summary>
-        /// The _user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-
-        /// <summary>
-        /// The _user data repository.
-        /// </summary>
-        private readonly IUserDataManager _userDataRepository;
-        /// <summary>
-        /// The _library manager.
-        /// </summary>
-        private readonly ILibraryManager _libraryManager;
-        private readonly IItemRepository _itemRepo;
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-
-        public AlbumsService(
-            ILogger<AlbumsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            IUserDataManager userDataRepository,
-            ILibraryManager libraryManager,
-            IItemRepository itemRepo,
-            IDtoService dtoService,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _userDataRepository = userDataRepository;
-            _libraryManager = libraryManager;
-            _itemRepo = itemRepo;
-            _dtoService = dtoService;
-            _authContext = authContext;
-        }
-
-        public object Get(GetSimilarArtists request)
-        {
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = SimilarItemsHelper.GetSimilarItemsResult(
-                dtoOptions, 
-                _userManager,
-                _itemRepo,
-                _libraryManager,
-                _userDataRepository,
-                _dtoService,
-                request, new[] { typeof(MusicArtist) },
-                SimilarItemsHelper.GetSimiliarityScore);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetSimilarAlbums request)
-        {
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = SimilarItemsHelper.GetSimilarItemsResult(
-                dtoOptions, 
-                _userManager,
-                _itemRepo,
-                _libraryManager,
-                _userDataRepository,
-                _dtoService,
-                request, new[] { typeof(MusicAlbum) },
-                GetAlbumSimilarityScore);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the album similarity score.
-        /// </summary>
-        /// <param name="item1">The item1.</param>
-        /// <param name="item1People">The item1 people.</param>
-        /// <param name="allPeople">All people.</param>
-        /// <param name="item2">The item2.</param>
-        /// <returns>System.Int32.</returns>
-        private int GetAlbumSimilarityScore(BaseItem item1, List<PersonInfo> item1People, List<PersonInfo> allPeople, BaseItem item2)
-        {
-            var points = SimilarItemsHelper.GetSimiliarityScore(item1, item1People, allPeople, item2);
-
-            var album1 = (MusicAlbum)item1;
-            var album2 = (MusicAlbum)item2;
-
-            var artists1 = album1
-                .GetAllArtists()
-                .DistinctNames()
-                .ToList();
-
-            var artists2 = new HashSet<string>(
-                album2.GetAllArtists().DistinctNames(),
-                StringComparer.OrdinalIgnoreCase);
-
-            return points + artists1.Where(artists2.Contains).Sum(i => 5);
-        }
-    }
-}

+ 0 - 196
MediaBrowser.Api/Music/InstantMixService.cs

@@ -1,196 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Playlists;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Music
-{
-    [Route("/Songs/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given song")]
-    public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Route("/Albums/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given album")]
-    public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Route("/Playlists/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given playlist")]
-    public class GetInstantMixFromPlaylist : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Route("/MusicGenres/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
-    public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
-    {
-        [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-    }
-
-    [Route("/Artists/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
-    public class GetInstantMixFromArtistId : BaseGetSimilarItems
-    {
-        [ApiMember(Name = "Id", Description = "The artist Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/MusicGenres/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
-    public class GetInstantMixFromMusicGenreId : BaseGetSimilarItems
-    {
-        [ApiMember(Name = "Id", Description = "The genre Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Items/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given item")]
-    public class GetInstantMixFromItem : BaseGetSimilarItemsFromItem
-    {
-    }
-
-    [Authenticated]
-    public class InstantMixService : BaseApiService
-    {
-        private readonly IUserManager _userManager;
-
-        private readonly IDtoService _dtoService;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IMusicManager _musicManager;
-        private readonly IAuthorizationContext _authContext;
-
-        public InstantMixService(
-            ILogger<InstantMixService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            IDtoService dtoService,
-            IMusicManager musicManager,
-            ILibraryManager libraryManager,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _dtoService = dtoService;
-            _musicManager = musicManager;
-            _libraryManager = libraryManager;
-            _authContext = authContext;
-        }
-
-        public object Get(GetInstantMixFromItem request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromArtistId request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromMusicGenreId request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromSong request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromAlbum request)
-        {
-            var album = _libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromPlaylist request)
-        {
-            var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        public object Get(GetInstantMixFromMusicGenre request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var items = _musicManager.GetInstantMixFromGenres(new[] { request.Name }, user, dtoOptions);
-
-            return GetResult(items, user, request, dtoOptions);
-        }
-
-        private object GetResult(List<BaseItem> items, User user, BaseGetSimilarItems request, DtoOptions dtoOptions)
-        {
-            var list = items;
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = list.Count
-            };
-
-            if (request.Limit.HasValue)
-            {
-                list = list.Take(request.Limit.Value).ToList();
-            }
-
-            var returnList = _dtoService.GetBaseItemDtos(list, dtoOptions, user);
-
-            result.Items = returnList;
-
-            return result;
-        }
-    }
-}

+ 0 - 197
MediaBrowser.Api/PackageService.cs

@@ -1,197 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Updates;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Updates;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Repositories", "GET", Summary = "Gets all package repositories")]
-    [Authenticated]
-    public class GetRepositories : IReturnVoid
-    {
-    }
-
-    [Route("/Repositories", "POST", Summary = "Sets the enabled and existing package repositories")]
-    [Authenticated]
-    public class SetRepositories : List<RepositoryInfo>, IReturnVoid
-    {
-    }
-
-    /// <summary>
-    /// Class GetPackage.
-    /// </summary>
-    [Route("/Packages/{Name}", "GET", Summary = "Gets a package, by name or assembly guid")]
-    [Authenticated]
-    public class GetPackage : IReturn<PackageInfo>
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The name of the package", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "AssemblyGuid", Description = "The guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string AssemblyGuid { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetPackages.
-    /// </summary>
-    [Route("/Packages", "GET", Summary = "Gets available packages")]
-    [Authenticated]
-    public class GetPackages : IReturn<PackageInfo[]>
-    {
-    }
-
-    /// <summary>
-    /// Class InstallPackage.
-    /// </summary>
-    [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")]
-    [Authenticated(Roles = "Admin")]
-    public class InstallPackage : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "Package name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "AssemblyGuid", Description = "Guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string AssemblyGuid { get; set; }
-
-        /// <summary>
-        /// Gets or sets the version.
-        /// </summary>
-        /// <value>The version.</value>
-        [ApiMember(Name = "Version", Description = "Optional version. Defaults to latest version.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Version { get; set; }
-    }
-
-    /// <summary>
-    /// Class CancelPackageInstallation.
-    /// </summary>
-    [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")]
-    [Authenticated(Roles = "Admin")]
-    public class CancelPackageInstallation : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Installation Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class PackageService.
-    /// </summary>
-    public class PackageService : BaseApiService
-    {
-        private readonly IInstallationManager _installationManager;
-        private readonly IServerConfigurationManager _serverConfigurationManager;
-
-        public PackageService(
-            ILogger<PackageService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IInstallationManager installationManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _installationManager = installationManager;
-            _serverConfigurationManager = serverConfigurationManager;
-        }
-
-        public object Get(GetRepositories request)
-        {
-            var result = _serverConfigurationManager.Configuration.PluginRepositories;
-            return ToOptimizedResult(result);
-        }
-
-        public void Post(SetRepositories request)
-        {
-            _serverConfigurationManager.Configuration.PluginRepositories = request;
-            _serverConfigurationManager.SaveConfiguration();
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPackage request)
-        {
-            var packages = _installationManager.GetAvailablePackages().GetAwaiter().GetResult();
-            var result = _installationManager.FilterPackages(
-                packages,
-                request.Name,
-                string.IsNullOrEmpty(request.AssemblyGuid) ? default : Guid.Parse(request.AssemblyGuid)).FirstOrDefault();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Get(GetPackages request)
-        {
-            IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
-
-            return ToOptimizedResult(packages.ToArray());
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException"></exception>
-        public async Task Post(InstallPackage request)
-        {
-            var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
-            var package = _installationManager.GetCompatibleVersions(
-                    packages,
-                    request.Name,
-                    string.IsNullOrEmpty(request.AssemblyGuid) ? Guid.Empty : Guid.Parse(request.AssemblyGuid),
-                    string.IsNullOrEmpty(request.Version) ? null : Version.Parse(request.Version)).FirstOrDefault();
-
-            if (package == null)
-            {
-                throw new ResourceNotFoundException(
-                    string.Format(
-                        CultureInfo.InvariantCulture,
-                        "Package not found: {0}",
-                        request.Name));
-            }
-
-            await _installationManager.InstallPackage(package);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Delete(CancelPackageInstallation request)
-        {
-            _installationManager.CancelInstallation(new Guid(request.Id));
-        }
-    }
-}

+ 0 - 216
MediaBrowser.Api/PlaylistService.cs

@@ -1,216 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Playlists;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Playlists;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Playlists", "POST", Summary = "Creates a new playlist")]
-    public class CreatePlaylist : IReturn<PlaylistCreationResult>
-    {
-        [ApiMember(Name = "Name", Description = "The name of the new playlist.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Name { get; set; }
-
-        [ApiMember(Name = "Ids", Description = "Item Ids to add to the playlist", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
-        public string Ids { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "MediaType", Description = "The playlist media type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string MediaType { get; set; }
-    }
-
-    [Route("/Playlists/{Id}/Items", "POST", Summary = "Adds items to a playlist")]
-    public class AddToPlaylist : IReturnVoid
-    {
-        [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Ids { get; set; }
-
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public Guid UserId { get; set; }
-    }
-
-    [Route("/Playlists/{Id}/Items/{ItemId}/Move/{NewIndex}", "POST", Summary = "Moves a playlist item")]
-    public class MoveItem : IReturnVoid
-    {
-        [ApiMember(Name = "ItemId", Description = "ItemId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ItemId { get; set; }
-
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "NewIndex", Description = "NewIndex", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public int NewIndex { get; set; }
-    }
-
-    [Route("/Playlists/{Id}/Items", "DELETE", Summary = "Removes items from a playlist")]
-    public class RemoveFromPlaylist : IReturnVoid
-    {
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "EntryIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string EntryIds { get; set; }
-    }
-
-    [Route("/Playlists/{Id}/Items", "GET", Summary = "Gets the original items of a playlist")]
-    public class GetPlaylistItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-    }
-
-    [Authenticated]
-    public class PlaylistService : BaseApiService
-    {
-        private readonly IPlaylistManager _playlistManager;
-        private readonly IDtoService _dtoService;
-        private readonly IUserManager _userManager;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IAuthorizationContext _authContext;
-
-        public PlaylistService(
-            ILogger<PlaylistService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IDtoService dtoService,
-            IPlaylistManager playlistManager,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _dtoService = dtoService;
-            _playlistManager = playlistManager;
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _authContext = authContext;
-        }
-
-        public void Post(MoveItem request)
-        {
-            _playlistManager.MoveItem(request.Id, request.ItemId, request.NewIndex);
-        }
-
-        public async Task<object> Post(CreatePlaylist request)
-        {
-            var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
-            {
-                Name = request.Name,
-                ItemIdList = GetGuids(request.Ids),
-                UserId = request.UserId,
-                MediaType = request.MediaType
-            }).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public void Post(AddToPlaylist request)
-        {
-            _playlistManager.AddToPlaylist(request.Id, GetGuids(request.Ids), request.UserId);
-        }
-
-        public void Delete(RemoveFromPlaylist request)
-        {
-            _playlistManager.RemoveFromPlaylist(request.Id, request.EntryIds.Split(','));
-        }
-
-        public object Get(GetPlaylistItems request)
-        {
-            var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var items = playlist.GetManageableItems().ToArray();
-
-            var count = items.Length;
-
-            if (request.StartIndex.HasValue)
-            {
-                items = items.Skip(request.StartIndex.Value).ToArray();
-            }
-
-            if (request.Limit.HasValue)
-            {
-                items = items.Take(request.Limit.Value).ToArray();
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
-
-            for (int index = 0; index < dtos.Count; index++)
-            {
-                dtos[index].PlaylistItemId = items[index].Item1.Id;
-            }
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = dtos,
-                TotalRecordCount = count
-            };
-
-            return ToOptimizedResult(result);
-        }
-    }
-}

+ 0 - 277
MediaBrowser.Api/PluginService.cs

@@ -1,277 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Common.Updates;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Plugins;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class Plugins.
-    /// </summary>
-    [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
-    [Authenticated]
-    public class GetPlugins : IReturn<PluginInfo[]>
-    {
-        public bool? IsAppStoreEnabled { get; set; }
-    }
-
-    /// <summary>
-    /// Class UninstallPlugin.
-    /// </summary>
-    [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
-    [Authenticated(Roles = "Admin")]
-    public class UninstallPlugin : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetPluginConfiguration.
-    /// </summary>
-    [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")]
-    [Authenticated]
-    public class GetPluginConfiguration
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdatePluginConfiguration.
-    /// </summary>
-    [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")]
-    [Authenticated]
-    public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// The raw Http Request Input Stream.
-        /// </summary>
-        /// <value>The request stream.</value>
-        public Stream RequestStream { get; set; }
-    }
-
-    // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins,
-    // delete all these registration endpoints. They are only kept for compatibility.
-    [Route("/Registrations/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
-    [Authenticated]
-    public class GetRegistration : IReturn<RegistrationInfo>
-    {
-        [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetPluginSecurityInfo.
-    /// </summary>
-    [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information", IsHidden = true)]
-    [Authenticated]
-    public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
-    {
-    }
-
-    /// <summary>
-    /// Class UpdatePluginSecurityInfo.
-    /// </summary>
-    [Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information", IsHidden = true)]
-    [Authenticated(Roles = "Admin")]
-    public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
-    {
-    }
-
-    [Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
-    [Authenticated]
-    public class GetRegistrationStatus
-    {
-        [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-    }
-
-    // TODO these two classes are only kept for compability with paid plugins and should be removed
-    public class RegistrationInfo
-    {
-        public string Name { get; set; }
-
-        public DateTime ExpirationDate { get; set; }
-
-        public bool IsTrial { get; set; }
-
-        public bool IsRegistered { get; set; }
-    }
-
-    public class MBRegistrationRecord
-    {
-        public DateTime ExpirationDate { get; set; }
-
-        public bool IsRegistered { get; set; }
-
-        public bool RegChecked { get; set; }
-
-        public bool RegError { get; set; }
-
-        public bool TrialVersion { get; set; }
-
-        public bool IsValid { get; set; }
-    }
-
-    public class PluginSecurityInfo
-    {
-        public string SupporterKey { get; set; }
-
-        public bool IsMBSupporter { get; set; }
-    }
-    /// <summary>
-    /// Class PluginsService.
-    /// </summary>
-    public class PluginService : BaseApiService
-    {
-        /// <summary>
-        /// The _json serializer.
-        /// </summary>
-        private readonly IJsonSerializer _jsonSerializer;
-
-        /// <summary>
-        /// The _app host.
-        /// </summary>
-        private readonly IApplicationHost _appHost;
-        private readonly IInstallationManager _installationManager;
-
-        public PluginService(
-            ILogger<PluginService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IJsonSerializer jsonSerializer,
-            IApplicationHost appHost,
-            IInstallationManager installationManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _appHost = appHost;
-            _installationManager = installationManager;
-            _jsonSerializer = jsonSerializer;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetRegistrationStatus request)
-        {
-            var record = new MBRegistrationRecord
-            {
-                IsRegistered = true,
-                RegChecked = true,
-                TrialVersion = false,
-                IsValid = true,
-                RegError = false
-            };
-
-            return ToOptimizedResult(record);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPlugins request)
-        {
-            var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray();
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPluginConfiguration request)
-        {
-            var guid = new Guid(request.Id);
-            var plugin = _appHost.Plugins.First(p => p.Id == guid) as IHasPluginConfiguration;
-
-            return ToOptimizedResult(plugin.Configuration);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPluginSecurityInfo request)
-        {
-            var result = new PluginSecurityInfo
-            {
-                IsMBSupporter = true,
-                SupporterKey = "IAmTotallyLegit"
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(UpdatePluginSecurityInfo request)
-        {
-            return Task.CompletedTask;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public async Task Post(UpdatePluginConfiguration request)
-        {
-            // We need to parse this manually because we told service stack not to with IRequiresRequestStream
-            // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
-            var id = Guid.Parse(GetPathValue(1));
-
-            if (!(_appHost.Plugins.First(p => p.Id == id) is IHasPluginConfiguration plugin))
-            {
-                throw new FileNotFoundException();
-            }
-
-            var configuration = (await _jsonSerializer.DeserializeFromStreamAsync(request.RequestStream, plugin.ConfigurationType).ConfigureAwait(false)) as BasePluginConfiguration;
-
-            plugin.UpdateConfiguration(configuration);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Delete(UninstallPlugin request)
-        {
-            var guid = new Guid(request.Id);
-            var plugin = _appHost.Plugins.First(p => p.Id == guid);
-
-            _installationManager.UninstallPlugin(plugin);
-        }
-    }
-}

+ 0 - 234
MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs

@@ -1,234 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Tasks;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.ScheduledTasks
-{
-    /// <summary>
-    /// Class GetScheduledTask.
-    /// </summary>
-    [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
-    public class GetScheduledTask : IReturn<TaskInfo>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetScheduledTasks.
-    /// </summary>
-    [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
-    public class GetScheduledTasks : IReturn<TaskInfo[]>
-    {
-        [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsHidden { get; set; }
-
-        [ApiMember(Name = "IsEnabled", Description = "Optional filter tasks that are enabled, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsEnabled { get; set; }
-    }
-
-    /// <summary>
-    /// Class StartScheduledTask.
-    /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
-    public class StartScheduledTask : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class StopScheduledTask.
-    /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
-    public class StopScheduledTask : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateScheduledTaskTriggers.
-    /// </summary>
-    [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
-    public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the task id.
-        /// </summary>
-        /// <value>The task id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class ScheduledTasksService.
-    /// </summary>
-    [Authenticated(Roles = "Admin")]
-    public class ScheduledTaskService : BaseApiService
-    {
-        /// <summary>
-        /// The task manager.
-        /// </summary>
-        private readonly ITaskManager _taskManager;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScheduledTaskService" /> class.
-        /// </summary>
-        /// <param name="taskManager">The task manager.</param>
-        /// <exception cref="ArgumentNullException">taskManager</exception>
-        public ScheduledTaskService(
-            ILogger<ScheduledTaskService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ITaskManager taskManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _taskManager = taskManager;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>IEnumerable{TaskInfo}.</returns>
-        public object Get(GetScheduledTasks request)
-        {
-            IEnumerable<IScheduledTaskWorker> result = _taskManager.ScheduledTasks
-                .OrderBy(i => i.Name);
-
-            if (request.IsHidden.HasValue)
-            {
-                var val = request.IsHidden.Value;
-
-                result = result.Where(i =>
-                {
-                    var isHidden = false;
-
-                    if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
-                    {
-                        isHidden = configurableTask.IsHidden;
-                    }
-
-                    return isHidden == val;
-                });
-            }
-
-            if (request.IsEnabled.HasValue)
-            {
-                var val = request.IsEnabled.Value;
-
-                result = result.Where(i =>
-                {
-                    var isEnabled = true;
-
-                    if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
-                    {
-                        isEnabled = configurableTask.IsEnabled;
-                    }
-
-                    return isEnabled == val;
-                });
-            }
-
-            var infos = result
-                .Select(ScheduledTaskHelpers.GetTaskInfo)
-                .ToArray();
-
-            return ToOptimizedResult(infos);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>IEnumerable{TaskInfo}.</returns>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public object Get(GetScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            var result = ScheduledTaskHelpers.GetTaskInfo(task);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Post(StartScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            _taskManager.Execute(task, new TaskOptions());
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Delete(StopScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            _taskManager.Cancel(task);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Post(UpdateScheduledTaskTriggers request)
-        {
-            // We need to parse this manually because we told service stack not to with IRequiresRequestStream
-            // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
-            var id = GetPathValue(1).ToString();
-
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.Ordinal));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            task.Triggers = request.ToArray();
-        }
-    }
-}

+ 0 - 332
MediaBrowser.Api/SearchService.cs

@@ -1,332 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Drawing;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Search;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetSearchHints.
-    /// </summary>
-    [Route("/Search/Hints", "GET", Summary = "Gets search hints based on a search term")]
-    public class GetSearchHints : IReturn<SearchHintResult>
-    {
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Supply a user id to search within a user's library or omit to search all.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Search characters used to find items.
-        /// </summary>
-        /// <value>The index by.</value>
-        [ApiMember(Name = "SearchTerm", Description = "The search term to filter on", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SearchTerm { get; set; }
-
-
-        [ApiMember(Name = "IncludePeople", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludePeople { get; set; }
-
-        [ApiMember(Name = "IncludeMedia", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludeMedia { get; set; }
-
-        [ApiMember(Name = "IncludeGenres", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludeGenres { get; set; }
-
-        [ApiMember(Name = "IncludeStudios", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludeStudios { get; set; }
-
-        [ApiMember(Name = "IncludeArtists", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool IncludeArtists { get; set; }
-
-        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string IncludeItemTypes { get; set; }
-
-        [ApiMember(Name = "ExcludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ExcludeItemTypes { get; set; }
-
-        [ApiMember(Name = "MediaTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string MediaTypes { get; set; }
-
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsMovie { get; set; }
-
-        [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSeries { get; set; }
-
-        [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsNews { get; set; }
-
-        [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsKids { get; set; }
-
-        [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
-        public bool? IsSports { get; set; }
-
-        public GetSearchHints()
-        {
-            IncludeArtists = true;
-            IncludeGenres = true;
-            IncludeMedia = true;
-            IncludePeople = true;
-            IncludeStudios = true;
-        }
-    }
-
-    /// <summary>
-    /// Class SearchService.
-    /// </summary>
-    [Authenticated]
-    public class SearchService : BaseApiService
-    {
-        /// <summary>
-        /// The _search engine.
-        /// </summary>
-        private readonly ISearchEngine _searchEngine;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IDtoService _dtoService;
-        private readonly IImageProcessor _imageProcessor;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SearchService" /> class.
-        /// </summary>
-        /// <param name="searchEngine">The search engine.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <param name="dtoService">The dto service.</param>
-        /// <param name="imageProcessor">The image processor.</param>
-        public SearchService(
-            ILogger<SearchService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ISearchEngine searchEngine,
-            ILibraryManager libraryManager,
-            IDtoService dtoService,
-            IImageProcessor imageProcessor)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _searchEngine = searchEngine;
-            _libraryManager = libraryManager;
-            _dtoService = dtoService;
-            _imageProcessor = imageProcessor;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetSearchHints request)
-        {
-            var result = GetSearchHintsAsync(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the search hints async.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{IEnumerable{SearchHintResult}}.</returns>
-        private SearchHintResult GetSearchHintsAsync(GetSearchHints request)
-        {
-            var result = _searchEngine.GetSearchHints(new SearchQuery
-            {
-                Limit = request.Limit,
-                SearchTerm = request.SearchTerm,
-                IncludeArtists = request.IncludeArtists,
-                IncludeGenres = request.IncludeGenres,
-                IncludeMedia = request.IncludeMedia,
-                IncludePeople = request.IncludePeople,
-                IncludeStudios = request.IncludeStudios,
-                StartIndex = request.StartIndex,
-                UserId = request.UserId,
-                IncludeItemTypes = ApiEntryPoint.Split(request.IncludeItemTypes, ',', true),
-                ExcludeItemTypes = ApiEntryPoint.Split(request.ExcludeItemTypes, ',', true),
-                MediaTypes = ApiEntryPoint.Split(request.MediaTypes, ',', true),
-                ParentId = request.ParentId,
-
-                IsKids = request.IsKids,
-                IsMovie = request.IsMovie,
-                IsNews = request.IsNews,
-                IsSeries = request.IsSeries,
-                IsSports = request.IsSports
-            });
-
-            return new SearchHintResult
-            {
-                TotalRecordCount = result.TotalRecordCount,
-
-                SearchHints = result.Items.Select(GetSearchHintResult).ToArray()
-            };
-        }
-
-        /// <summary>
-        /// Gets the search hint result.
-        /// </summary>
-        /// <param name="hintInfo">The hint info.</param>
-        /// <returns>SearchHintResult.</returns>
-        private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
-        {
-            var item = hintInfo.Item;
-
-            var result = new SearchHint
-            {
-                Name = item.Name,
-                IndexNumber = item.IndexNumber,
-                ParentIndexNumber = item.ParentIndexNumber,
-                Id = item.Id,
-                Type = item.GetClientTypeName(),
-                MediaType = item.MediaType,
-                MatchedTerm = hintInfo.MatchedTerm,
-                RunTimeTicks = item.RunTimeTicks,
-                ProductionYear = item.ProductionYear,
-                ChannelId = item.ChannelId,
-                EndDate = item.EndDate
-            };
-
-            // legacy
-            result.ItemId = result.Id;
-
-            if (item.IsFolder)
-            {
-                result.IsFolder = true;
-            }
-
-            var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
-
-            if (primaryImageTag != null)
-            {
-                result.PrimaryImageTag = primaryImageTag;
-                result.PrimaryImageAspectRatio = _dtoService.GetPrimaryImageAspectRatio(item);
-            }
-
-            SetThumbImageInfo(result, item);
-            SetBackdropImageInfo(result, item);
-
-            switch (item)
-            {
-                case IHasSeries hasSeries:
-                    result.Series = hasSeries.SeriesName;
-                    break;
-                case LiveTvProgram program:
-                    result.StartDate = program.StartDate;
-                    break;
-                case Series series:
-                    if (series.Status.HasValue)
-                    {
-                        result.Status = series.Status.Value.ToString();
-                    }
-
-                    break;
-                case MusicAlbum album:
-                    result.Artists = album.Artists;
-                    result.AlbumArtist = album.AlbumArtist;
-                    break;
-                case Audio song:
-                    result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
-                    result.Artists = song.Artists;
-
-                    MusicAlbum musicAlbum = song.AlbumEntity;
-
-                    if (musicAlbum != null)
-                    {
-                        result.Album = musicAlbum.Name;
-                        result.AlbumId = musicAlbum.Id;
-                    }
-                    else
-                    {
-                        result.Album = song.Album;
-                    }
-
-                    break;
-            }
-
-            if (!item.ChannelId.Equals(Guid.Empty))
-            {
-                var channel = _libraryManager.GetItemById(item.ChannelId);
-                result.ChannelName = channel?.Name;
-            }
-
-            return result;
-        }
-
-        private void SetThumbImageInfo(SearchHint hint, BaseItem item)
-        {
-            var itemWithImage = item.HasImage(ImageType.Thumb) ? item : null;
-
-            if (itemWithImage == null && item is Episode)
-            {
-                itemWithImage = GetParentWithImage<Series>(item, ImageType.Thumb);
-            }
-
-            if (itemWithImage == null)
-            {
-                itemWithImage = GetParentWithImage<BaseItem>(item, ImageType.Thumb);
-            }
-
-            if (itemWithImage != null)
-            {
-                var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Thumb);
-
-                if (tag != null)
-                {
-                    hint.ThumbImageTag = tag;
-                    hint.ThumbImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
-                }
-            }
-        }
-
-        private void SetBackdropImageInfo(SearchHint hint, BaseItem item)
-        {
-            var itemWithImage = (item.HasImage(ImageType.Backdrop) ? item : null)
-                ?? GetParentWithImage<BaseItem>(item, ImageType.Backdrop);
-
-            if (itemWithImage != null)
-            {
-                var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Backdrop);
-
-                if (tag != null)
-                {
-                    hint.BackdropImageTag = tag;
-                    hint.BackdropImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
-                }
-            }
-        }
-
-        private T GetParentWithImage<T>(BaseItem item, ImageType type)
-            where T : BaseItem
-        {
-            return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
-        }
-    }
-}

+ 0 - 499
MediaBrowser.Api/Sessions/SessionService.cs

@@ -1,499 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Session;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Sessions
-{
-    /// <summary>
-    /// Class GetSessions.
-    /// </summary>
-    [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
-    [Authenticated]
-    public class GetSessions : IReturn<SessionInfo[]>
-    {
-        [ApiMember(Name = "ControllableByUserId", Description = "Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid ControllableByUserId { get; set; }
-
-        [ApiMember(Name = "DeviceId", Description = "Filter by device Id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string DeviceId { get; set; }
-
-        public int? ActiveWithinSeconds { get; set; }
-    }
-
-    /// <summary>
-    /// Class DisplayContent.
-    /// </summary>
-    [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")]
-    [Authenticated]
-    public class DisplayContent : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Artist, Genre, Studio, Person, or any kind of BaseItem.
-        /// </summary>
-        /// <value>The type of the item.</value>
-        [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ItemType { get; set; }
-
-        /// <summary>
-        /// Artist name, genre name, item Id, etc.
-        /// </summary>
-        /// <value>The item identifier.</value>
-        [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ItemId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name of the item.
-        /// </summary>
-        /// <value>The name of the item.</value>
-        [ApiMember(Name = "ItemName", Description = "The name of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ItemName { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")]
-    [Authenticated]
-    public class Play : PlayRequest
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
-    [Authenticated]
-    public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
-    [Authenticated]
-    public class SendSystemCommand : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the command.
-        /// </summary>
-        /// <value>The play command.</value>
-        [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Command { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")]
-    [Authenticated]
-    public class SendGeneralCommand : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the command.
-        /// </summary>
-        /// <value>The play command.</value>
-        [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Command { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")]
-    [Authenticated]
-    public class SendFullGeneralCommand : GeneralCommand, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
-    [Authenticated]
-    public class SendMessageCommand : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "Text", Description = "The message text.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Text { get; set; }
-
-        [ApiMember(Name = "Header", Description = "The message header.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Header { get; set; }
-
-        [ApiMember(Name = "TimeoutMs", Description = "The message timeout. If omitted the user will have to confirm viewing the message.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public long? TimeoutMs { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")]
-    [Authenticated]
-    public class AddUserToSession : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string UserId { get; set; }
-    }
-
-    [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")]
-    [Authenticated]
-    public class RemoveUserFromSession : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string UserId { get; set; }
-    }
-
-    [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")]
-    [Authenticated]
-    public class PostCapabilities : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string PlayableMediaTypes { get; set; }
-
-        [ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string SupportedCommands { get; set; }
-
-        [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
-        public bool SupportsMediaControl { get; set; }
-
-        [ApiMember(Name = "SupportsSync", Description = "Determines whether sync is supported.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
-        public bool SupportsSync { get; set; }
-
-        [ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
-        public bool SupportsPersistentIdentifier { get; set; }
-
-        public PostCapabilities()
-        {
-            SupportsPersistentIdentifier = true;
-        }
-    }
-
-    [Route("/Sessions/Capabilities/Full", "POST", Summary = "Updates capabilities for a device")]
-    [Authenticated]
-    public class PostFullCapabilities : ClientCapabilities, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Sessions/Viewing", "POST", Summary = "Reports that a session is viewing an item")]
-    [Authenticated]
-    public class ReportViewing : IReturnVoid
-    {
-        [ApiMember(Name = "SessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string SessionId { get; set; }
-
-        [ApiMember(Name = "ItemId", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string ItemId { get; set; }
-    }
-
-    [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
-    [Authenticated]
-    public class ReportSessionEnded : IReturnVoid
-    {
-    }
-
-    [Route("/Auth/Providers", "GET")]
-    [Authenticated(Roles = "Admin")]
-    public class GetAuthProviders : IReturn<NameIdPair[]>
-    {
-    }
-
-    [Route("/Auth/PasswordResetProviders", "GET")]
-    [Authenticated(Roles = "Admin")]
-    public class GetPasswordResetProviders : IReturn<NameIdPair[]>
-    {
-    }
-
-    /// <summary>
-    /// Class SessionsService.
-    /// </summary>
-    public class SessionService : BaseApiService
-    {
-        /// <summary>
-        /// The session manager.
-        /// </summary>
-        private readonly ISessionManager _sessionManager;
-
-        private readonly IUserManager _userManager;
-        private readonly IAuthorizationContext _authContext;
-        private readonly IDeviceManager _deviceManager;
-        private readonly ISessionContext _sessionContext;
-
-        public SessionService(
-            ILogger<SessionService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ISessionManager sessionManager,
-            IUserManager userManager,
-            IAuthorizationContext authContext,
-            IDeviceManager deviceManager,
-            ISessionContext sessionContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _sessionManager = sessionManager;
-            _userManager = userManager;
-            _authContext = authContext;
-            _deviceManager = deviceManager;
-            _sessionContext = sessionContext;
-        }
-
-        public object Get(GetAuthProviders request)
-        {
-            return _userManager.GetAuthenticationProviders();
-        }
-
-        public object Get(GetPasswordResetProviders request)
-        {
-            return _userManager.GetPasswordResetProviders();
-        }
-
-        public void Post(ReportSessionEnded request)
-        {
-            var auth = _authContext.GetAuthorizationInfo(Request);
-
-            _sessionManager.Logout(auth.Token);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetSessions request)
-        {
-            var result = _sessionManager.Sessions;
-
-            if (!string.IsNullOrEmpty(request.DeviceId))
-            {
-                result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase));
-            }
-
-            if (!request.ControllableByUserId.Equals(Guid.Empty))
-            {
-                result = result.Where(i => i.SupportsRemoteControl);
-
-                var user = _userManager.GetUserById(request.ControllableByUserId);
-
-                if (!user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers))
-                {
-                    result = result.Where(i => i.UserId.Equals(Guid.Empty) || i.ContainsUser(request.ControllableByUserId));
-                }
-
-                if (!user.HasPermission(PermissionKind.EnableSharedDeviceControl))
-                {
-                    result = result.Where(i => !i.UserId.Equals(Guid.Empty));
-                }
-
-                if (request.ActiveWithinSeconds.HasValue && request.ActiveWithinSeconds.Value > 0)
-                {
-                    var minActiveDate = DateTime.UtcNow.AddSeconds(0 - request.ActiveWithinSeconds.Value);
-                    result = result.Where(i => i.LastActivityDate >= minActiveDate);
-                }
-
-                result = result.Where(i =>
-                {
-                    var deviceId = i.DeviceId;
-
-                    if (!string.IsNullOrWhiteSpace(deviceId))
-                    {
-                        if (!_deviceManager.CanAccessDevice(user, deviceId))
-                        {
-                            return false;
-                        }
-                    }
-
-                    return true;
-                });
-            }
-
-            return ToOptimizedResult(result.ToArray());
-        }
-
-        public Task Post(SendPlaystateCommand request)
-        {
-            return _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(DisplayContent request)
-        {
-            var command = new BrowseRequest
-            {
-                ItemId = request.ItemId,
-                ItemName = request.ItemName,
-                ItemType = request.ItemType
-            };
-
-            return _sessionManager.SendBrowseCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(SendSystemCommand request)
-        {
-            var name = request.Command;
-            if (Enum.TryParse(name, true, out GeneralCommandType commandType))
-            {
-                name = commandType.ToString();
-            }
-
-            var currentSession = GetSession(_sessionContext);
-            var command = new GeneralCommand
-            {
-                Name = name,
-                ControllingUserId = currentSession.UserId
-            };
-
-            return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(SendMessageCommand request)
-        {
-            var command = new MessageCommand
-            {
-                Header = string.IsNullOrEmpty(request.Header) ? "Message from Server" : request.Header,
-                TimeoutMs = request.TimeoutMs,
-                Text = request.Text
-            };
-
-            return _sessionManager.SendMessageCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(Play request)
-        {
-            return _sessionManager.SendPlayCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
-        }
-
-        public Task Post(SendGeneralCommand request)
-        {
-            var currentSession = GetSession(_sessionContext);
-
-            var command = new GeneralCommand
-            {
-                Name = request.Command,
-                ControllingUserId = currentSession.UserId
-            };
-
-            return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
-        }
-
-        public Task Post(SendFullGeneralCommand request)
-        {
-            var currentSession = GetSession(_sessionContext);
-
-            request.ControllingUserId = currentSession.UserId;
-
-            return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None);
-        }
-
-        public void Post(AddUserToSession request)
-        {
-            _sessionManager.AddAdditionalUser(request.Id, new Guid(request.UserId));
-        }
-
-        public void Delete(RemoveUserFromSession request)
-        {
-            _sessionManager.RemoveAdditionalUser(request.Id, new Guid(request.UserId));
-        }
-
-        public void Post(PostCapabilities request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Id))
-            {
-                request.Id = GetSession(_sessionContext).Id;
-            }
-
-            _sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
-            {
-                PlayableMediaTypes = SplitValue(request.PlayableMediaTypes, ','),
-                SupportedCommands = SplitValue(request.SupportedCommands, ','),
-                SupportsMediaControl = request.SupportsMediaControl,
-                SupportsSync = request.SupportsSync,
-                SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
-            });
-        }
-
-        public void Post(PostFullCapabilities request)
-        {
-            if (string.IsNullOrWhiteSpace(request.Id))
-            {
-                request.Id = GetSession(_sessionContext).Id;
-            }
-
-            _sessionManager.ReportCapabilities(request.Id, request);
-        }
-
-        public void Post(ReportViewing request)
-        {
-            request.SessionId = GetSession(_sessionContext).Id;
-
-            _sessionManager.ReportNowViewingItem(request.SessionId, request.ItemId);
-        }
-    }
-}

+ 0 - 302
MediaBrowser.Api/Subtitles/SubtitleService.cs

@@ -1,302 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Controller.Subtitles;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
-
-namespace MediaBrowser.Api.Subtitles
-{
-    [Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")]
-    [Authenticated(Roles = "Admin")]
-    public class DeleteSubtitle
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-
-        [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")]
-        public int Index { get; set; }
-    }
-
-    [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
-    [Authenticated]
-    public class SearchRemoteSubtitles : IReturn<RemoteSubtitleInfo[]>
-    {
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid Id { get; set; }
-
-        [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Language { get; set; }
-
-        public bool? IsPerfectMatch { get; set; }
-    }
-
-    [Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")]
-    [Authenticated]
-    public class DownloadRemoteSubtitles : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-
-        [ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string SubtitleId { get; set; }
-    }
-
-    [Route("/Providers/Subtitles/Subtitles/{Id}", "GET")]
-    [Authenticated]
-    public class GetRemoteSubtitles : IReturnVoid
-    {
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
-    [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/{StartPositionTicks}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
-    public class GetSubtitle
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid Id { get; set; }
-
-        [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string MediaSourceId { get; set; }
-
-        [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
-        public int Index { get; set; }
-
-        [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Format { get; set; }
-
-        [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public long StartPositionTicks { get; set; }
-
-        [ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public long? EndPositionTicks { get; set; }
-
-        [ApiMember(Name = "CopyTimestamps", Description = "CopyTimestamps", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool CopyTimestamps { get; set; }
-
-        public bool AddVttTimeMap { get; set; }
-    }
-
-    [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
-    [Authenticated]
-    public class GetSubtitlePlaylist
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string MediaSourceId { get; set; }
-
-        [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
-        public int Index { get; set; }
-
-        [ApiMember(Name = "SegmentLength", Description = "The subtitle srgment length", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int SegmentLength { get; set; }
-    }
-
-    public class SubtitleService : BaseApiService
-    {
-        private readonly ILibraryManager _libraryManager;
-        private readonly ISubtitleManager _subtitleManager;
-        private readonly ISubtitleEncoder _subtitleEncoder;
-        private readonly IMediaSourceManager _mediaSourceManager;
-        private readonly IProviderManager _providerManager;
-        private readonly IFileSystem _fileSystem;
-        private readonly IAuthorizationContext _authContext;
-
-        public SubtitleService(
-            ILogger<SubtitleService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ILibraryManager libraryManager,
-            ISubtitleManager subtitleManager,
-            ISubtitleEncoder subtitleEncoder,
-            IMediaSourceManager mediaSourceManager,
-            IProviderManager providerManager,
-            IFileSystem fileSystem,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _libraryManager = libraryManager;
-            _subtitleManager = subtitleManager;
-            _subtitleEncoder = subtitleEncoder;
-            _mediaSourceManager = mediaSourceManager;
-            _providerManager = providerManager;
-            _fileSystem = fileSystem;
-            _authContext = authContext;
-        }
-
-        public async Task<object> Get(GetSubtitlePlaylist request)
-        {
-            var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
-
-            var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false);
-
-            var builder = new StringBuilder();
-
-            var runtime = mediaSource.RunTimeTicks ?? -1;
-
-            if (runtime <= 0)
-            {
-                throw new ArgumentException("HLS Subtitles are not supported for this media.");
-            }
-
-            var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
-            if (segmentLengthTicks <= 0)
-            {
-                throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)");
-            }
-
-            builder.AppendLine("#EXTM3U");
-            builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture));
-            builder.AppendLine("#EXT-X-VERSION:3");
-            builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
-            builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-
-            long positionTicks = 0;
-
-            var accessToken = _authContext.GetAuthorizationInfo(Request).Token;
-
-            while (positionTicks < runtime)
-            {
-                var remaining = runtime - positionTicks;
-                var lengthTicks = Math.Min(remaining, segmentLengthTicks);
-
-                builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture) + ",");
-
-                var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
-
-                var url = string.Format("stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
-                    positionTicks.ToString(CultureInfo.InvariantCulture),
-                    endPositionTicks.ToString(CultureInfo.InvariantCulture),
-                    accessToken);
-
-                builder.AppendLine(url);
-
-                positionTicks += segmentLengthTicks;
-            }
-
-            builder.AppendLine("#EXT-X-ENDLIST");
-
-            return ResultFactory.GetResult(Request, builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
-        }
-
-        public async Task<object> Get(GetSubtitle request)
-        {
-            if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
-            {
-                request.Format = "json";
-            }
-
-            if (string.IsNullOrEmpty(request.Format))
-            {
-                var item = (Video)_libraryManager.GetItemById(request.Id);
-
-                var idString = request.Id.ToString("N", CultureInfo.InvariantCulture);
-                var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null)
-                    .First(i => string.Equals(i.Id, request.MediaSourceId ?? idString));
-
-                var subtitleStream = mediaSource.MediaStreams
-                    .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index);
-
-                return await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false);
-            }
-
-            if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
-            {
-                using var stream = await GetSubtitles(request).ConfigureAwait(false);
-                using var reader = new StreamReader(stream);
-
-                var text = reader.ReadToEnd();
-
-                text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
-
-                return ResultFactory.GetResult(Request, text, MimeTypes.GetMimeType("file." + request.Format));
-            }
-
-            return ResultFactory.GetResult(Request, await GetSubtitles(request).ConfigureAwait(false), MimeTypes.GetMimeType("file." + request.Format));
-        }
-
-        private Task<Stream> GetSubtitles(GetSubtitle request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-
-            return _subtitleEncoder.GetSubtitles(item,
-                request.MediaSourceId,
-                request.Index,
-                request.Format,
-                request.StartPositionTicks,
-                request.EndPositionTicks ?? 0,
-                request.CopyTimestamps,
-                CancellationToken.None);
-        }
-
-        public async Task<object> Get(SearchRemoteSubtitles request)
-        {
-            var video = (Video)_libraryManager.GetItemById(request.Id);
-
-            return await _subtitleManager.SearchSubtitles(video, request.Language, request.IsPerfectMatch, CancellationToken.None).ConfigureAwait(false);
-        }
-
-        public Task Delete(DeleteSubtitle request)
-        {
-            var item = _libraryManager.GetItemById(request.Id);
-            return _subtitleManager.DeleteSubtitles(item, request.Index);
-        }
-
-        public async Task<object> Get(GetRemoteSubtitles request)
-        {
-            var result = await _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).ConfigureAwait(false);
-
-            return ResultFactory.GetResult(Request, result.Stream, MimeTypes.GetMimeType("file." + result.Format));
-        }
-
-        public void Post(DownloadRemoteSubtitles request)
-        {
-            var video = (Video)_libraryManager.GetItemById(request.Id);
-
-            Task.Run(async () =>
-            {
-                try
-                {
-                    await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
-                        .ConfigureAwait(false);
-
-                    _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);
-                }
-                catch (Exception ex)
-                {
-                    Logger.LogError(ex, "Error downloading subtitles");
-                }
-            });
-        }
-    }
-}

+ 0 - 103
MediaBrowser.Api/SuggestionsService.cs

@@ -1,103 +0,0 @@
-using System;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    [Route("/Users/{UserId}/Suggestions", "GET", Summary = "Gets items based on a query.")]
-    public class GetSuggestedItems : IReturn<QueryResult<BaseItemDto>>
-    {
-        public string MediaType { get; set; }
-
-        public string Type { get; set; }
-
-        public Guid UserId { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        public int? StartIndex { get; set; }
-
-        public int? Limit { get; set; }
-
-        public string[] GetMediaTypes()
-        {
-            return (MediaType ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetIncludeItemTypes()
-        {
-            return (Type ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-    }
-
-    public class SuggestionsService : BaseApiService
-    {
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-        private readonly IUserManager _userManager;
-        private readonly ILibraryManager _libraryManager;
-
-        public SuggestionsService(
-            ILogger<SuggestionsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IDtoService dtoService,
-            IAuthorizationContext authContext,
-            IUserManager userManager,
-            ILibraryManager libraryManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _dtoService = dtoService;
-            _authContext = authContext;
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-        }
-
-        public object Get(GetSuggestedItems request)
-        {
-            return GetResultItems(request);
-        }
-
-        private QueryResult<BaseItemDto> GetResultItems(GetSuggestedItems request)
-        {
-            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-            var result = GetItems(request, user, dtoOptions);
-
-            var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
-
-            return new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = result.TotalRecordCount,
-                Items = dtoList
-            };
-        }
-
-        private QueryResult<BaseItem> GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions)
-        {
-            return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
-            {
-                OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
-                MediaTypes = request.GetMediaTypes(),
-                IncludeItemTypes = request.GetIncludeItemTypes(),
-                IsVirtualItem = false,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                DtoOptions = dtoOptions,
-                EnableTotalRecordCount = request.EnableTotalRecordCount,
-                Recursive = true
-            });
-        }
-    }
-}

+ 0 - 69
MediaBrowser.Api/System/ActivityLogService.cs

@@ -1,69 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Activity;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.System
-{
-    [Route("/System/ActivityLog/Entries", "GET", Summary = "Gets activity log entries")]
-    public class GetActivityLogs : IReturn<QueryResult<ActivityLogEntry>>
-    {
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MinDate { get; set; }
-
-        public bool? HasUserId { get; set; }
-    }
-
-    [Authenticated(Roles = "Admin")]
-    public class ActivityLogService : BaseApiService
-    {
-        private readonly IActivityManager _activityManager;
-
-        public ActivityLogService(
-            ILogger<ActivityLogService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IActivityManager activityManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _activityManager = activityManager;
-        }
-
-        public object Get(GetActivityLogs request)
-        {
-            DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
-                (DateTime?)null :
-                DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-
-            var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
-                entries => entries.Where(entry => entry.DateCreated >= minDate
-                                                  && (!request.HasUserId.HasValue || (request.HasUserId.Value
-                                                      ? entry.UserId != Guid.Empty
-                                                      : entry.UserId == Guid.Empty))));
-
-            var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit);
-
-            return ToOptimizedResult(result);
-        }
-    }
-}

+ 0 - 221
MediaBrowser.Api/System/SystemService.cs

@@ -1,221 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.System
-{
-    /// <summary>
-    /// Class GetSystemInfo.
-    /// </summary>
-    [Route("/System/Info", "GET", Summary = "Gets information about the server")]
-    [Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)]
-    public class GetSystemInfo : IReturn<SystemInfo>
-    {
-    }
-
-    [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")]
-    public class GetPublicSystemInfo : IReturn<PublicSystemInfo>
-    {
-    }
-
-    [Route("/System/Ping", "POST")]
-    [Route("/System/Ping", "GET")]
-    public class PingSystem : IReturnVoid
-    {
-    }
-
-    /// <summary>
-    /// Class RestartApplication.
-    /// </summary>
-    [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
-    [Authenticated(Roles = "Admin", AllowLocal = true)]
-    public class RestartApplication
-    {
-    }
-
-    /// <summary>
-    /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server.
-    /// </summary>
-    [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")]
-    [Authenticated(Roles = "Admin", AllowLocal = true)]
-    public class ShutdownApplication
-    {
-    }
-
-    [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
-    [Authenticated(Roles = "Admin")]
-    public class GetServerLogs : IReturn<LogFile[]>
-    {
-    }
-
-    [Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
-    [Authenticated]
-    public class GetEndpointInfo : IReturn<EndPointInfo>
-    {
-        public string Endpoint { get; set; }
-    }
-
-    [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")]
-    [Authenticated(Roles = "Admin")]
-    public class GetLogFile
-    {
-        [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Name { get; set; }
-    }
-
-    [Route("/System/WakeOnLanInfo", "GET", Summary = "Gets wake on lan information")]
-    [Authenticated]
-    public class GetWakeOnLanInfo : IReturn<WakeOnLanInfo[]>
-    {
-    }
-
-    /// <summary>
-    /// Class SystemInfoService.
-    /// </summary>
-    public class SystemService : BaseApiService
-    {
-        /// <summary>
-        /// The _app host.
-        /// </summary>
-        private readonly IServerApplicationHost _appHost;
-        private readonly IApplicationPaths _appPaths;
-        private readonly IFileSystem _fileSystem;
-
-        private readonly INetworkManager _network;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SystemService" /> class.
-        /// </summary>
-        /// <param name="appHost">The app host.</param>
-        /// <param name="fileSystem">The file system.</param>
-        /// <exception cref="ArgumentNullException">jsonSerializer</exception>
-        public SystemService(
-            ILogger<SystemService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IServerApplicationHost appHost,
-            IFileSystem fileSystem,
-            INetworkManager network)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _appPaths = serverConfigurationManager.ApplicationPaths;
-            _appHost = appHost;
-            _fileSystem = fileSystem;
-            _network = network;
-        }
-
-        public object Post(PingSystem request)
-        {
-            return _appHost.Name;
-        }
-
-        public object Get(GetWakeOnLanInfo request)
-        {
-            var result = _appHost.GetWakeOnLanInfo();
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetServerLogs request)
-        {
-            IEnumerable<FileSystemMetadata> files;
-
-            try
-            {
-                files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false);
-            }
-            catch (IOException ex)
-            {
-                Logger.LogError(ex, "Error getting logs");
-                files = Enumerable.Empty<FileSystemMetadata>();
-            }
-
-            var result = files.Select(i => new LogFile
-            {
-                DateCreated = _fileSystem.GetCreationTimeUtc(i),
-                DateModified = _fileSystem.GetLastWriteTimeUtc(i),
-                Name = i.Name,
-                Size = i.Length
-            }).OrderByDescending(i => i.DateModified)
-                .ThenByDescending(i => i.DateCreated)
-                .ThenBy(i => i.Name)
-                .ToArray();
-
-            return ToOptimizedResult(result);
-        }
-
-        public Task<object> Get(GetLogFile request)
-        {
-            var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
-                .First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
-
-            // For older files, assume fully static
-            var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite;
-
-            return ResultFactory.GetStaticFileResult(Request, file.FullName, fileShare);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Get(GetSystemInfo request)
-        {
-            var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Get(GetPublicSystemInfo request)
-        {
-            var result = await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(RestartApplication request)
-        {
-            _appHost.Restart();
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(ShutdownApplication request)
-        {
-            Task.Run(async () =>
-            {
-                await Task.Delay(100).ConfigureAwait(false);
-                await _appHost.Shutdown().ConfigureAwait(false);
-            });
-        }
-
-        public object Get(GetEndpointInfo request)
-        {
-            return ToOptimizedResult(new EndPointInfo
-            {
-                IsLocal = Request.IsLocal,
-                IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
-            });
-        }
-    }
-}

+ 0 - 497
MediaBrowser.Api/TvShowsService.cs

@@ -1,497 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.TV;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetNextUpEpisodes.
-    /// </summary>
-    [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")]
-    public class GetNextUpEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SeriesId { get; set; }
-
-        /// <summary>
-        /// Specify this to localize the search to a specific item or folder. Omit to use the root.
-        /// </summary>
-        /// <value>The parent id.</value>
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        public GetNextUpEpisodes()
-        {
-            EnableTotalRecordCount = true;
-        }
-    }
-
-    [Route("/Shows/Upcoming", "GET", Summary = "Gets a list of upcoming episodes")]
-    public class GetUpcomingEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        /// <summary>
-        /// Specify this to localize the search to a specific item or folder. Omit to use the root.
-        /// </summary>
-        /// <value>The parent id.</value>
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-    }
-
-    [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")]
-    public class GetEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public int? Season { get; set; }
-
-        [ApiMember(Name = "SeasonId", Description = "Optional. Filter by season id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SeasonId { get; set; }
-
-        [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsMissing { get; set; }
-
-        [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string AdjacentTo { get; set; }
-
-        [ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string StartItemId { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string SortBy { get; set; }
-
-        [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public SortOrder? SortOrder { get; set; }
-    }
-
-    [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")]
-    public class GetSeasons : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsSpecialSeason { get; set; }
-
-        [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsMissing { get; set; }
-
-        [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string AdjacentTo { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-    }
-
-    /// <summary>
-    /// Class TvShowsService.
-    /// </summary>
-    [Authenticated]
-    public class TvShowsService : BaseApiService
-    {
-        /// <summary>
-        /// The _user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-
-        /// <summary>
-        /// The _library manager.
-        /// </summary>
-        private readonly ILibraryManager _libraryManager;
-
-        private readonly IDtoService _dtoService;
-        private readonly ITVSeriesManager _tvSeriesManager;
-        private readonly IAuthorizationContext _authContext;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="TvShowsService" /> class.
-        /// </summary>
-        /// <param name="userManager">The user manager.</param>
-        /// <param name="userDataManager">The user data repository.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        public TvShowsService(
-            ILogger<TvShowsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IDtoService dtoService,
-            ITVSeriesManager tvSeriesManager,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _dtoService = dtoService;
-            _tvSeriesManager = tvSeriesManager;
-            _authContext = authContext;
-        }
-
-        public object Get(GetUpcomingEpisodes request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1);
-
-            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
-
-            var options = GetDtoOptions(_authContext, request);
-
-            var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = new[] { typeof(Episode).Name },
-                OrderBy = new[] { ItemSortBy.PremiereDate, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
-                MinPremiereDate = minPremiereDate,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                ParentId = parentIdGuid,
-                Recursive = true,
-                DtoOptions = options
-            });
-
-            var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = itemsResult.Count,
-                Items = returnItems
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetNextUpEpisodes request)
-        {
-            var options = GetDtoOptions(_authContext, request);
-
-            var result = _tvSeriesManager.GetNextUp(new NextUpQuery
-            {
-                Limit = request.Limit,
-                ParentId = request.ParentId,
-                SeriesId = request.SeriesId,
-                StartIndex = request.StartIndex,
-                UserId = request.UserId,
-                EnableTotalRecordCount = request.EnableTotalRecordCount
-            }, options);
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user);
-
-            return ToOptimizedResult(new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = result.TotalRecordCount,
-                Items = returnItems
-            });
-        }
-
-        /// <summary>
-        /// Applies the paging.
-        /// </summary>
-        /// <param name="items">The items.</param>
-        /// <param name="startIndex">The start index.</param>
-        /// <param name="limit">The limit.</param>
-        /// <returns>IEnumerable{BaseItem}.</returns>
-        private IEnumerable<BaseItem> ApplyPaging(IEnumerable<BaseItem> items, int? startIndex, int? limit)
-        {
-            // Start at
-            if (startIndex.HasValue)
-            {
-                items = items.Skip(startIndex.Value);
-            }
-
-            // Return limit
-            if (limit.HasValue)
-            {
-                items = items.Take(limit.Value);
-            }
-
-            return items;
-        }
-
-        public object Get(GetSeasons request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var series = GetSeries(request.Id);
-
-            if (series == null)
-            {
-                throw new ResourceNotFoundException("Series not found");
-            }
-
-            var seasons = series.GetItemList(new InternalItemsQuery(user)
-            {
-                IsMissing = request.IsMissing,
-                IsSpecialSeason = request.IsSpecialSeason,
-                AdjacentTo = request.AdjacentTo
-            });
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);
-
-            return new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = returnItems.Count,
-                Items = returnItems
-            };
-        }
-
-        private Series GetSeries(string seriesId)
-        {
-            if (!string.IsNullOrWhiteSpace(seriesId))
-            {
-                return _libraryManager.GetItemById(seriesId) as Series;
-            }
-
-            return null;
-        }
-
-        public object Get(GetEpisodes request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            List<BaseItem> episodes;
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            if (!string.IsNullOrWhiteSpace(request.SeasonId))
-            {
-                if (!(_libraryManager.GetItemById(new Guid(request.SeasonId)) is Season season))
-                {
-                    throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId);
-                }
-
-                episodes = season.GetEpisodes(user, dtoOptions);
-            }
-            else if (request.Season.HasValue)
-            {
-                var series = GetSeries(request.Id);
-
-                if (series == null)
-                {
-                    throw new ResourceNotFoundException("Series not found");
-                }
-
-                var season = series.GetSeasons(user, dtoOptions).FirstOrDefault(i => i.IndexNumber == request.Season.Value);
-
-                episodes = season == null ? new List<BaseItem>() : ((Season)season).GetEpisodes(user, dtoOptions);
-            }
-            else
-            {
-                var series = GetSeries(request.Id);
-
-                if (series == null)
-                {
-                    throw new ResourceNotFoundException("Series not found");
-                }
-
-                episodes = series.GetEpisodes(user, dtoOptions).ToList();
-            }
-
-            // Filter after the fact in case the ui doesn't want them
-            if (request.IsMissing.HasValue)
-            {
-                var val = request.IsMissing.Value;
-                episodes = episodes.Where(i => ((Episode)i).IsMissingEpisode == val).ToList();
-            }
-
-            if (!string.IsNullOrWhiteSpace(request.StartItemId))
-            {
-                episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N", CultureInfo.InvariantCulture), request.StartItemId, StringComparison.OrdinalIgnoreCase)).ToList();
-            }
-
-            // This must be the last filter
-            if (!string.IsNullOrEmpty(request.AdjacentTo))
-            {
-                episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo).ToList();
-            }
-
-            if (string.Equals(request.SortBy, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
-            {
-                episodes.Shuffle();
-            }
-
-            var returnItems = episodes;
-
-            if (request.StartIndex.HasValue || request.Limit.HasValue)
-            {
-                returnItems = ApplyPaging(episodes, request.StartIndex, request.Limit).ToList();
-            }
-
-            var dtos = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user);
-
-            return new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = episodes.Count,
-                Items = dtos
-            };
-        }
-    }
-}

+ 0 - 143
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -1,143 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetArtists.
-    /// </summary>
-    [Route("/Artists", "GET", Summary = "Gets all artists from a given item, folder, or the entire library")]
-    public class GetArtists : GetItemsByName
-    {
-    }
-
-    [Route("/Artists/AlbumArtists", "GET", Summary = "Gets all album artists from a given item, folder, or the entire library")]
-    public class GetAlbumArtists : GetItemsByName
-    {
-    }
-
-    [Route("/Artists/{Name}", "GET", Summary = "Gets an artist, by name")]
-    public class GetArtist : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class ArtistsService.
-    /// </summary>
-    [Authenticated]
-    public class ArtistsService : BaseItemsByNameService<MusicArtist>
-    {
-        public ArtistsService(
-            ILogger<ArtistsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(
-                logger,
-                serverConfigurationManager,
-                httpResultFactory,
-                userManager,
-                libraryManager,
-                userDataRepository,
-                dtoService,
-                authorizationContext)
-        {
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetArtist request)
-        {
-            return GetItem(request);
-        }
-
-        /// <summary>
-        /// Gets the item.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto}.</returns>
-        private BaseItemDto GetItem(GetArtist request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            var item = GetArtist(request.Name, LibraryManager, dtoOptions);
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-
-                return DtoService.GetBaseItemDto(item, dtoOptions, user);
-            }
-
-            return DtoService.GetBaseItemDto(item, dtoOptions);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetArtists request)
-        {
-            return GetResultSlim(request);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetAlbumArtists request)
-        {
-            var result = GetResultSlim(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
-        {
-            return request is GetAlbumArtists ? LibraryManager.GetAlbumArtists(query) : LibraryManager.GetArtists(query);
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
-        protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}

+ 0 - 388
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -1,388 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class BaseItemsByNameService.
-    /// </summary>
-    /// <typeparam name="TItemType">The type of the T item type.</typeparam>
-    public abstract class BaseItemsByNameService<TItemType> : BaseApiService
-        where TItemType : BaseItem, IItemByName
-    {
-        /// <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>
-        /// <param name="userDataRepository">The user data repository.</param>
-        /// <param name="dtoService">The dto service.</param>
-        protected BaseItemsByNameService(
-            ILogger<BaseItemsByNameService<TItemType>> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            UserManager = userManager;
-            LibraryManager = libraryManager;
-            UserDataRepository = userDataRepository;
-            DtoService = dtoService;
-            AuthorizationContext = authorizationContext;
-        }
-
-        /// <summary>
-        /// Gets the _user manager.
-        /// </summary>
-        protected IUserManager UserManager { get; }
-
-        /// <summary>
-        /// Gets the library manager.
-        /// </summary>
-        protected ILibraryManager LibraryManager { get; }
-
-        protected IUserDataManager UserDataRepository { get; }
-
-        protected IDtoService DtoService { get; }
-
-        protected IAuthorizationContext AuthorizationContext { get; }
-
-        protected BaseItem GetParentItem(GetItemsByName request)
-        {
-            BaseItem parentItem;
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
-            }
-            else
-            {
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
-            }
-
-            return parentItem;
-        }
-
-        protected string GetParentItemViewType(GetItemsByName request)
-        {
-            var parent = GetParentItem(request);
-
-            if (parent is IHasCollectionType collectionFolder)
-            {
-                return collectionFolder.CollectionType;
-            }
-
-            return null;
-        }
-
-        protected QueryResult<BaseItemDto> GetResultSlim(GetItemsByName request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            User user = null;
-            BaseItem parentItem;
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                user = UserManager.GetUserById(request.UserId);
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
-            }
-            else
-            {
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
-            }
-
-            var excludeItemTypes = request.GetExcludeItemTypes();
-            var includeItemTypes = request.GetIncludeItemTypes();
-            var mediaTypes = request.GetMediaTypes();
-
-            var query = new InternalItemsQuery(user)
-            {
-                ExcludeItemTypes = excludeItemTypes,
-                IncludeItemTypes = includeItemTypes,
-                MediaTypes = mediaTypes,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                IsFavorite = request.IsFavorite,
-                NameLessThan = request.NameLessThan,
-                NameStartsWith = request.NameStartsWith,
-                NameStartsWithOrGreater = request.NameStartsWithOrGreater,
-                Tags = request.GetTags(),
-                OfficialRatings = request.GetOfficialRatings(),
-                Genres = request.GetGenres(),
-                GenreIds = GetGuids(request.GenreIds),
-                StudioIds = GetGuids(request.StudioIds),
-                Person = request.Person,
-                PersonIds = GetGuids(request.PersonIds),
-                PersonTypes = request.GetPersonTypes(),
-                Years = request.GetYears(),
-                MinCommunityRating = request.MinCommunityRating,
-                DtoOptions = dtoOptions,
-                SearchTerm = request.SearchTerm,
-                EnableTotalRecordCount = request.EnableTotalRecordCount
-            };
-
-            if (!string.IsNullOrWhiteSpace(request.ParentId))
-            {
-                if (parentItem is Folder)
-                {
-                    query.AncestorIds = new[] { new Guid(request.ParentId) };
-                }
-                else
-                {
-                    query.ItemIds = new[] { new Guid(request.ParentId) };
-                }
-            }
-
-            // Studios
-            if (!string.IsNullOrEmpty(request.Studios))
-            {
-                query.StudioIds = request.Studios.Split('|').Select(i =>
-                {
-                    try
-                    {
-                        return LibraryManager.GetStudio(i);
-                    }
-                    catch
-                    {
-                        return null;
-                    }
-                }).Where(i => i != null).Select(i => i.Id).ToArray();
-            }
-
-            foreach (var filter in request.GetFilters())
-            {
-                switch (filter)
-                {
-                    case ItemFilter.Dislikes:
-                        query.IsLiked = false;
-                        break;
-                    case ItemFilter.IsFavorite:
-                        query.IsFavorite = true;
-                        break;
-                    case ItemFilter.IsFavoriteOrLikes:
-                        query.IsFavoriteOrLiked = true;
-                        break;
-                    case ItemFilter.IsFolder:
-                        query.IsFolder = true;
-                        break;
-                    case ItemFilter.IsNotFolder:
-                        query.IsFolder = false;
-                        break;
-                    case ItemFilter.IsPlayed:
-                        query.IsPlayed = true;
-                        break;
-                    case ItemFilter.IsResumable:
-                        query.IsResumable = true;
-                        break;
-                    case ItemFilter.IsUnplayed:
-                        query.IsPlayed = false;
-                        break;
-                    case ItemFilter.Likes:
-                        query.IsLiked = true;
-                        break;
-                }
-            }
-
-            var result = GetItems(request, query);
-
-            var dtos = result.Items.Select(i =>
-            {
-                var dto = DtoService.GetItemByNameDto(i.Item1, dtoOptions, null, user);
-
-                if (!string.IsNullOrWhiteSpace(request.IncludeItemTypes))
-                {
-                    SetItemCounts(dto, i.Item2);
-                }
-
-                return dto;
-            });
-
-            return new QueryResult<BaseItemDto>
-            {
-                Items = dtos.ToArray(),
-                TotalRecordCount = result.TotalRecordCount
-            };
-        }
-
-        protected virtual QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
-        {
-            return new QueryResult<(BaseItem, ItemCounts)>();
-        }
-
-        private void SetItemCounts(BaseItemDto dto, ItemCounts counts)
-        {
-            dto.ChildCount = counts.ItemCount;
-            dto.ProgramCount = counts.ProgramCount;
-            dto.SeriesCount = counts.SeriesCount;
-            dto.EpisodeCount = counts.EpisodeCount;
-            dto.MovieCount = counts.MovieCount;
-            dto.TrailerCount = counts.TrailerCount;
-            dto.AlbumCount = counts.AlbumCount;
-            dto.SongCount = counts.SongCount;
-            dto.ArtistCount = counts.ArtistCount;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{ItemsResult}.</returns>
-        protected QueryResult<BaseItemDto> GetResult(GetItemsByName request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            User user = null;
-            BaseItem parentItem;
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                user = UserManager.GetUserById(request.UserId);
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
-            }
-            else
-            {
-                parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
-            }
-
-            IList<BaseItem> items;
-
-            var excludeItemTypes = request.GetExcludeItemTypes();
-            var includeItemTypes = request.GetIncludeItemTypes();
-            var mediaTypes = request.GetMediaTypes();
-
-            var query = new InternalItemsQuery(user)
-            {
-                ExcludeItemTypes = excludeItemTypes,
-                IncludeItemTypes = includeItemTypes,
-                MediaTypes = mediaTypes,
-                DtoOptions = dtoOptions
-            };
-
-            bool Filter(BaseItem i) => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes);
-
-            if (parentItem.IsFolder)
-            {
-                var folder = (Folder)parentItem;
-
-                if (!request.UserId.Equals(Guid.Empty))
-                {
-                    items = request.Recursive ?
-                        folder.GetRecursiveChildren(user, query).ToList() :
-                        folder.GetChildren(user, true).Where(Filter).ToList();
-                }
-                else
-                {
-                    items = request.Recursive ?
-                        folder.GetRecursiveChildren(Filter) :
-                        folder.Children.Where(Filter).ToList();
-                }
-            }
-            else
-            {
-                items = new[] { parentItem }.Where(Filter).ToList();
-            }
-
-            var extractedItems = GetAllItems(request, items);
-
-            var filteredItems = LibraryManager.Sort(extractedItems, user, request.GetOrderBy());
-
-            var ibnItemsArray = filteredItems.ToList();
-
-            IEnumerable<BaseItem> ibnItems = ibnItemsArray;
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                TotalRecordCount = ibnItemsArray.Count
-            };
-
-            if (request.StartIndex.HasValue || request.Limit.HasValue)
-            {
-                if (request.StartIndex.HasValue)
-                {
-                    ibnItems = ibnItems.Skip(request.StartIndex.Value);
-                }
-
-                if (request.Limit.HasValue)
-                {
-                    ibnItems = ibnItems.Take(request.Limit.Value);
-                }
-            }
-
-            var tuples = ibnItems.Select(i => new Tuple<BaseItem, List<BaseItem>>(i, new List<BaseItem>()));
-
-            var dtos = tuples.Select(i => DtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user));
-
-            result.Items = dtos.Where(i => i != null).ToArray();
-
-            return result;
-        }
-
-        /// <summary>
-        /// Filters the items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="f">The f.</param>
-        /// <param name="excludeItemTypes">The exclude item types.</param>
-        /// <param name="includeItemTypes">The include item types.</param>
-        /// <param name="mediaTypes">The media types.</param>
-        /// <returns>IEnumerable{BaseItem}.</returns>
-        private bool FilterItem(GetItemsByName request, BaseItem f, string[] excludeItemTypes, string[] includeItemTypes, string[] mediaTypes)
-        {
-            // Exclude item types
-            if (excludeItemTypes.Length > 0 && excludeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-
-            // Include item types
-            if (includeItemTypes.Length > 0 && !includeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-
-            // Include MediaTypes
-            if (mediaTypes.Length > 0 && !mediaTypes.Contains(f.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Task{`0}}.</returns>
-        protected abstract IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items);
-    }
-
-    /// <summary>
-    /// Class GetItemsByName.
-    /// </summary>
-    public class GetItemsByName : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
-    {
-        public GetItemsByName()
-        {
-            Recursive = true;
-        }
-    }
-}

+ 0 - 478
MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs

@@ -1,478 +0,0 @@
-using System;
-using System.Linq;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    public abstract class BaseItemsRequest : IHasDtoOptions
-    {
-        protected BaseItemsRequest()
-        {
-            EnableImages = true;
-            EnableTotalRecordCount = true;
-        }
-
-        /// <summary>
-        /// Gets or sets the max offical rating.
-        /// </summary>
-        /// <value>The max offical rating.</value>
-        [ApiMember(Name = "MaxOfficialRating", Description = "Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MaxOfficialRating { get; set; }
-
-        [ApiMember(Name = "HasThemeSong", Description = "Optional filter by items with theme songs.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasThemeSong { get; set; }
-
-        [ApiMember(Name = "HasThemeVideo", Description = "Optional filter by items with theme videos.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasThemeVideo { get; set; }
-
-        [ApiMember(Name = "HasSubtitles", Description = "Optional filter by items with subtitles.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasSubtitles { get; set; }
-
-        [ApiMember(Name = "HasSpecialFeature", Description = "Optional filter by items with special features.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasSpecialFeature { get; set; }
-
-        [ApiMember(Name = "HasTrailer", Description = "Optional filter by items with trailers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasTrailer { get; set; }
-
-        [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string AdjacentTo { get; set; }
-
-        [ApiMember(Name = "MinIndexNumber", Description = "Optional filter by minimum index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? MinIndexNumber { get; set; }
-
-        [ApiMember(Name = "ParentIndexNumber", Description = "Optional filter by parent index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ParentIndexNumber { get; set; }
-
-        [ApiMember(Name = "HasParentalRating", Description = "Optional filter by items that have or do not have a parental rating", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasParentalRating { get; set; }
-
-        [ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsHD { get; set; }
-
-        public bool? Is4K { get; set; }
-
-        [ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string LocationTypes { get; set; }
-
-        [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ExcludeLocationTypes { get; set; }
-
-        [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsMissing { get; set; }
-
-        [ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsUnaired { get; set; }
-
-        [ApiMember(Name = "MinCommunityRating", Description = "Optional filter by minimum community rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public double? MinCommunityRating { get; set; }
-
-        [ApiMember(Name = "MinCriticRating", Description = "Optional filter by minimum critic rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public double? MinCriticRating { get; set; }
-
-        [ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? AiredDuringSeason { get; set; }
-
-        [ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MinPremiereDate { get; set; }
-
-        [ApiMember(Name = "MinDateLastSaved", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MinDateLastSaved { get; set; }
-
-        [ApiMember(Name = "MinDateLastSavedForUser", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MinDateLastSavedForUser { get; set; }
-
-        [ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MaxPremiereDate { get; set; }
-
-        [ApiMember(Name = "HasOverview", Description = "Optional filter by items that have an overview or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasOverview { get; set; }
-
-        [ApiMember(Name = "HasImdbId", Description = "Optional filter by items that have an imdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasImdbId { get; set; }
-
-        [ApiMember(Name = "HasTmdbId", Description = "Optional filter by items that have a tmdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasTmdbId { get; set; }
-
-        [ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? HasTvdbId { get; set; }
-
-        [ApiMember(Name = "ExcludeItemIds", Description = "Optional. If specified, results will be filtered by exxcluding item ids. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ExcludeItemIds { get; set; }
-
-        public bool EnableTotalRecordCount { get; set; }
-
-        /// <summary>
-        /// Skips over a given number of items within the results. Use for paging.
-        /// </summary>
-        /// <value>The start index.</value>
-        [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? StartIndex { get; set; }
-
-        /// <summary>
-        /// The maximum number of items to return.
-        /// </summary>
-        /// <value>The limit.</value>
-        [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? Limit { get; set; }
-
-        /// <summary>
-        /// Whether or not to perform the query recursively.
-        /// </summary>
-        /// <value><c>true</c> if recursive; otherwise, <c>false</c>.</value>
-        [ApiMember(Name = "Recursive", Description = "When searching within folders, this determines whether or not the search will be recursive. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool Recursive { get; set; }
-
-        public string SearchTerm { get; set; }
-
-        /// <summary>
-        /// Gets or sets the sort order.
-        /// </summary>
-        /// <value>The sort order.</value>
-        [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string SortOrder { get; set; }
-
-        /// <summary>
-        /// Specify this to localize the search to a specific item or folder. Omit to use the root.
-        /// </summary>
-        /// <value>The parent id.</value>
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
-
-        /// <summary>
-        /// Fields to return within the items, in addition to basic information.
-        /// </summary>
-        /// <value>The fields.</value>
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        /// <summary>
-        /// Gets or sets the exclude item types.
-        /// </summary>
-        /// <value>The exclude item types.</value>
-        [ApiMember(Name = "ExcludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ExcludeItemTypes { get; set; }
-
-        /// <summary>
-        /// Gets or sets the include item types.
-        /// </summary>
-        /// <value>The include item types.</value>
-        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string IncludeItemTypes { get; set; }
-
-        /// <summary>
-        /// Filters to apply to the results.
-        /// </summary>
-        /// <value>The filters.</value>
-        [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Filters { get; set; }
-
-        /// <summary>
-        /// Gets or sets the Isfavorite option.
-        /// </summary>
-        /// <value>IsFavorite</value>
-        [ApiMember(Name = "IsFavorite", Description = "Optional filter by items that are marked as favorite, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsFavorite { get; set; }
-
-        /// <summary>
-        /// Gets or sets the media types.
-        /// </summary>
-        /// <value>The media types.</value>
-        [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string MediaTypes { get; set; }
-
-        /// <summary>
-        /// Gets or sets the image types.
-        /// </summary>
-        /// <value>The image types.</value>
-        [ApiMember(Name = "ImageTypes", Description = "Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ImageTypes { get; set; }
-
-        /// <summary>
-        /// What to sort the results by.
-        /// </summary>
-        /// <value>The sort by.</value>
-        [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string SortBy { get; set; }
-
-        [ApiMember(Name = "IsPlayed", Description = "Optional filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsPlayed { get; set; }
-
-        /// <summary>
-        /// Limit results to items containing specific genres.
-        /// </summary>
-        /// <value>The genres.</value>
-        [ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Genres { get; set; }
-
-        public string GenreIds { get; set; }
-
-        [ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string OfficialRatings { get; set; }
-
-        [ApiMember(Name = "Tags", Description = "Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Tags { get; set; }
-
-        /// <summary>
-        /// Limit results to items containing specific years.
-        /// </summary>
-        /// <value>The years.</value>
-        [ApiMember(Name = "Years", Description = "Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Years { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        /// <summary>
-        /// Limit results to items containing a specific person.
-        /// </summary>
-        /// <value>The person.</value>
-        [ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string Person { get; set; }
-
-        [ApiMember(Name = "PersonIds", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string PersonIds { get; set; }
-
-        /// <summary>
-        /// If the Person filter is used, this can also be used to restrict to a specific person type.
-        /// </summary>
-        /// <value>The type of the person.</value>
-        [ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string PersonTypes { get; set; }
-
-        /// <summary>
-        /// Limit results to items containing specific studios.
-        /// </summary>
-        /// <value>The studios.</value>
-        [ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Studios { get; set; }
-
-        [ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string StudioIds { get; set; }
-
-        /// <summary>
-        /// Gets or sets the studios.
-        /// </summary>
-        /// <value>The studios.</value>
-        [ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Artists { get; set; }
-
-        public string ExcludeArtistIds { get; set; }
-
-        [ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string ArtistIds { get; set; }
-
-        public string AlbumArtistIds { get; set; }
-
-        public string ContributingArtistIds { get; set; }
-
-        [ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Albums { get; set; }
-
-        public string AlbumIds { get; set; }
-
-        /// <summary>
-        /// Gets or sets the item ids.
-        /// </summary>
-        /// <value>The item ids.</value>
-        [ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Ids { get; set; }
-
-        /// <summary>
-        /// Gets or sets the video types.
-        /// </summary>
-        /// <value>The video types.</value>
-        [ApiMember(Name = "VideoTypes", Description = "Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string VideoTypes { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the min offical rating.
-        /// </summary>
-        /// <value>The min offical rating.</value>
-        [ApiMember(Name = "MinOfficialRating", Description = "Optional filter by minimum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string MinOfficialRating { get; set; }
-
-        [ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? IsLocked { get; set; }
-
-        [ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? IsPlaceHolder { get; set; }
-
-        [ApiMember(Name = "HasOfficialRating", Description = "Optional filter by items that have official ratings", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public bool? HasOfficialRating { get; set; }
-
-        [ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? CollapseBoxSetItems { get; set; }
-
-        public int? MinWidth { get; set; }
-
-        public int? MinHeight { get; set; }
-
-        public int? MaxWidth { get; set; }
-
-        public int? MaxHeight { get; set; }
-
-        /// <summary>
-        /// Gets or sets the video formats.
-        /// </summary>
-        /// <value>The video formats.</value>
-        [ApiMember(Name = "Is3D", Description = "Optional filter by items that are 3D, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? Is3D { get; set; }
-
-        /// <summary>
-        /// Gets or sets the series status.
-        /// </summary>
-        /// <value>The series status.</value>
-        [ApiMember(Name = "SeriesStatus", Description = "Optional filter by Series Status. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string SeriesStatus { get; set; }
-
-        [ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string NameStartsWithOrGreater { get; set; }
-
-        [ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string NameStartsWith { get; set; }
-
-        [ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string NameLessThan { get; set; }
-
-        public string[] GetGenres()
-        {
-            return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetTags()
-        {
-            return (Tags ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetOfficialRatings()
-        {
-            return (OfficialRatings ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetMediaTypes()
-        {
-            return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetIncludeItemTypes()
-        {
-            return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetExcludeItemTypes()
-        {
-            return (ExcludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public int[] GetYears()
-        {
-            return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
-        }
-
-        public string[] GetStudios()
-        {
-            return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public string[] GetPersonTypes()
-        {
-            return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        public VideoType[] GetVideoTypes()
-        {
-            return string.IsNullOrEmpty(VideoTypes)
-                ? Array.Empty<VideoType>()
-                : VideoTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
-                    .Select(v => Enum.Parse<VideoType>(v, true)).ToArray();
-        }
-
-        /// <summary>
-        /// Gets the filters.
-        /// </summary>
-        /// <returns>IEnumerable{ItemFilter}.</returns>
-        public ItemFilter[] GetFilters()
-        {
-            var val = Filters;
-
-            return string.IsNullOrEmpty(val)
-                ? Array.Empty<ItemFilter>()
-                : val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
-                    .Select(v => Enum.Parse<ItemFilter>(v, true)).ToArray();
-        }
-
-        /// <summary>
-        /// Gets the image types.
-        /// </summary>
-        /// <returns>IEnumerable{ImageType}.</returns>
-        public ImageType[] GetImageTypes()
-        {
-            var val = ImageTypes;
-
-            return string.IsNullOrEmpty(val)
-                ? Array.Empty<ImageType>()
-                : val.Split(',').Select(v => Enum.Parse<ImageType>(v, true)).ToArray();
-        }
-
-        /// <summary>
-        /// Gets the order by.
-        /// </summary>
-        /// <returns>IEnumerable{ItemSortBy}.</returns>
-        public ValueTuple<string, SortOrder>[] GetOrderBy()
-        {
-            return GetOrderBy(SortBy, SortOrder);
-        }
-
-        public static ValueTuple<string, SortOrder>[] GetOrderBy(string sortBy, string requestedSortOrder)
-        {
-            var val = sortBy;
-
-            if (string.IsNullOrEmpty(val))
-            {
-                return Array.Empty<ValueTuple<string, SortOrder>>();
-            }
-
-            var vals = val.Split(',');
-            if (string.IsNullOrWhiteSpace(requestedSortOrder))
-            {
-                requestedSortOrder = "Ascending";
-            }
-
-            var sortOrders = requestedSortOrder.Split(',');
-
-            var result = new ValueTuple<string, SortOrder>[vals.Length];
-
-            for (var i = 0; i < vals.Length; i++)
-            {
-                var sortOrderIndex = sortOrders.Length > i ? i : 0;
-
-                var sortOrderValue = sortOrders.Length > sortOrderIndex ? sortOrders[sortOrderIndex] : null;
-                var sortOrder = string.Equals(sortOrderValue, "Descending", StringComparison.OrdinalIgnoreCase)
-                    ? MediaBrowser.Model.Entities.SortOrder.Descending
-                    : MediaBrowser.Model.Entities.SortOrder.Ascending;
-
-                result[i] = new ValueTuple<string, SortOrder>(vals[i], sortOrder);
-            }
-
-            return result;
-        }
-    }
-}

+ 0 - 140
MediaBrowser.Api/UserLibrary/GenresService.cs

@@ -1,140 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetGenres.
-    /// </summary>
-    [Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")]
-    public class GetGenres : GetItemsByName
-    {
-    }
-
-    /// <summary>
-    /// Class GetGenre.
-    /// </summary>
-    [Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")]
-    public class GetGenre : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class GenresService.
-    /// </summary>
-    [Authenticated]
-    public class GenresService : BaseItemsByNameService<Genre>
-    {
-        public GenresService(
-            ILogger<GenresService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(
-                logger,
-                serverConfigurationManager,
-                httpResultFactory,
-                userManager,
-                libraryManager,
-                userDataRepository,
-                dtoService,
-                authorizationContext)
-        {
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetGenre request)
-        {
-            var result = GetItem(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the item.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto}.</returns>
-        private BaseItemDto GetItem(GetGenre request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            var item = GetGenre(request.Name, LibraryManager, dtoOptions);
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-
-                return DtoService.GetBaseItemDto(item, dtoOptions, user);
-            }
-
-            return DtoService.GetBaseItemDto(item, dtoOptions);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetGenres request)
-        {
-            var result = GetResultSlim(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
-        {
-            var viewType = GetParentItemViewType(request);
-
-            if (string.Equals(viewType, CollectionType.Music) || string.Equals(viewType, CollectionType.MusicVideos))
-            {
-                return LibraryManager.GetMusicGenres(query);
-            }
-
-            return LibraryManager.GetGenres(query);
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
-        protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}

+ 0 - 514
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -1,514 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetItems.
-    /// </summary>
-    [Route("/Items", "GET", Summary = "Gets items based on a query.")]
-    [Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
-    public class GetItems : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
-    {
-    }
-
-    [Route("/Users/{UserId}/Items/Resume", "GET", Summary = "Gets items based on a query.")]
-    public class GetResumeItems : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
-    {
-    }
-
-    /// <summary>
-    /// Class ItemsService.
-    /// </summary>
-    [Authenticated]
-    public class ItemsService : BaseApiService
-    {
-        /// <summary>
-        /// The _user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-
-        /// <summary>
-        /// The _library manager.
-        /// </summary>
-        private readonly ILibraryManager _libraryManager;
-        private readonly ILocalizationManager _localization;
-
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemsService" /> class.
-        /// </summary>
-        /// <param name="userManager">The user manager.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <param name="localization">The localization.</param>
-        /// <param name="dtoService">The dto service.</param>
-        public ItemsService(
-            ILogger<ItemsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            ILocalizationManager localization,
-            IDtoService dtoService,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _localization = localization;
-            _dtoService = dtoService;
-            _authContext = authContext;
-        }
-
-        public object Get(GetResumeItems request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
-
-            var options = GetDtoOptions(_authContext, request);
-
-            var ancestorIds = Array.Empty<Guid>();
-
-            var excludeFolderIds = user.GetPreference(PreferenceKind.LatestItemExcludes);
-            if (parentIdGuid.Equals(Guid.Empty) && excludeFolderIds.Length > 0)
-            {
-                ancestorIds = _libraryManager.GetUserRootFolder().GetChildren(user, true)
-                    .Where(i => i is Folder)
-                    .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
-                    .Select(i => i.Id)
-                    .ToArray();
-            }
-
-            var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
-            {
-                OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) },
-                IsResumable = true,
-                StartIndex = request.StartIndex,
-                Limit = request.Limit,
-                ParentId = parentIdGuid,
-                Recursive = true,
-                DtoOptions = options,
-                MediaTypes = request.GetMediaTypes(),
-                IsVirtualItem = false,
-                CollapseBoxSetItems = false,
-                EnableTotalRecordCount = request.EnableTotalRecordCount,
-                AncestorIds = ancestorIds,
-                IncludeItemTypes = request.GetIncludeItemTypes(),
-                ExcludeItemTypes = request.GetExcludeItemTypes(),
-                SearchTerm = request.SearchTerm
-            });
-
-            var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                StartIndex = request.StartIndex.GetValueOrDefault(),
-                TotalRecordCount = itemsResult.TotalRecordCount,
-                Items = returnItems
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetItems request)
-        {
-            if (request == null)
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
-
-            var result = GetItems(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        private QueryResult<BaseItemDto> GetItems(GetItems request)
-        {
-            var user = request.UserId == Guid.Empty ? null : _userManager.GetUserById(request.UserId);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = GetQueryResult(request, dtoOptions, user);
-
-            if (result == null)
-            {
-                throw new InvalidOperationException("GetItemsToSerialize returned null");
-            }
-
-            if (result.Items == null)
-            {
-                throw new InvalidOperationException("GetItemsToSerialize result.Items returned null");
-            }
-
-            var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
-
-            return new QueryResult<BaseItemDto>
-            {
-                StartIndex = request.StartIndex.GetValueOrDefault(),
-                TotalRecordCount = result.TotalRecordCount,
-                Items = dtoList
-            };
-        }
-
-        /// <summary>
-        /// Gets the items to serialize.
-        /// </summary>
-        private QueryResult<BaseItem> GetQueryResult(GetItems request, DtoOptions dtoOptions, User user)
-        {
-            if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase)
-                || string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
-            {
-                request.ParentId = null;
-            }
-
-            BaseItem item = null;
-
-            if (!string.IsNullOrEmpty(request.ParentId))
-            {
-                item = _libraryManager.GetItemById(request.ParentId);
-            }
-
-            if (item == null)
-            {
-                item = _libraryManager.GetUserRootFolder();
-            }
-
-            if (!(item is Folder folder))
-            {
-                folder = _libraryManager.GetUserRootFolder();
-            }
-
-            if (folder is IHasCollectionType hasCollectionType
-                && string.Equals(hasCollectionType.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
-            {
-                request.Recursive = true;
-                request.IncludeItemTypes = "Playlist";
-            }
-
-            bool isInEnabledFolder = user.GetPreference(PreferenceKind.EnabledFolders).Any(i => new Guid(i) == item.Id)
-                    // Assume all folders inside an EnabledChannel are enabled
-                    || user.GetPreference(PreferenceKind.EnabledChannels).Any(i => new Guid(i) == item.Id);
-
-            var collectionFolders = _libraryManager.GetCollectionFolders(item);
-            foreach (var collectionFolder in collectionFolders)
-            {
-                if (user.GetPreference(PreferenceKind.EnabledFolders).Contains(
-                    collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture),
-                    StringComparer.OrdinalIgnoreCase))
-                {
-                    isInEnabledFolder = true;
-                }
-            }
-
-            if (!(item is UserRootFolder)
-                && !isInEnabledFolder
-                && !user.HasPermission(PermissionKind.EnableAllFolders)
-                && !user.HasPermission(PermissionKind.EnableAllChannels))
-            {
-                Logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Username, item.Name);
-                return new QueryResult<BaseItem>
-                {
-                    Items = Array.Empty<BaseItem>(),
-                    TotalRecordCount = 0,
-                    StartIndex = 0
-                };
-            }
-
-            if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || !(item is UserRootFolder))
-            {
-                return folder.GetItems(GetItemsQuery(request, dtoOptions, user));
-            }
-
-            var itemsArray = folder.GetChildren(user, true);
-            return new QueryResult<BaseItem>
-            {
-                Items = itemsArray,
-                TotalRecordCount = itemsArray.Count,
-                StartIndex = 0
-            };
-        }
-
-        private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions, User user)
-        {
-            var query = new InternalItemsQuery(user)
-            {
-                IsPlayed = request.IsPlayed,
-                MediaTypes = request.GetMediaTypes(),
-                IncludeItemTypes = request.GetIncludeItemTypes(),
-                ExcludeItemTypes = request.GetExcludeItemTypes(),
-                Recursive = request.Recursive,
-                OrderBy = request.GetOrderBy(),
-
-                IsFavorite = request.IsFavorite,
-                Limit = request.Limit,
-                StartIndex = request.StartIndex,
-                IsMissing = request.IsMissing,
-                IsUnaired = request.IsUnaired,
-                CollapseBoxSetItems = request.CollapseBoxSetItems,
-                NameLessThan = request.NameLessThan,
-                NameStartsWith = request.NameStartsWith,
-                NameStartsWithOrGreater = request.NameStartsWithOrGreater,
-                HasImdbId = request.HasImdbId,
-                IsPlaceHolder = request.IsPlaceHolder,
-                IsLocked = request.IsLocked,
-                MinWidth = request.MinWidth,
-                MinHeight = request.MinHeight,
-                MaxWidth = request.MaxWidth,
-                MaxHeight = request.MaxHeight,
-                Is3D = request.Is3D,
-                HasTvdbId = request.HasTvdbId,
-                HasTmdbId = request.HasTmdbId,
-                HasOverview = request.HasOverview,
-                HasOfficialRating = request.HasOfficialRating,
-                HasParentalRating = request.HasParentalRating,
-                HasSpecialFeature = request.HasSpecialFeature,
-                HasSubtitles = request.HasSubtitles,
-                HasThemeSong = request.HasThemeSong,
-                HasThemeVideo = request.HasThemeVideo,
-                HasTrailer = request.HasTrailer,
-                IsHD = request.IsHD,
-                Is4K = request.Is4K,
-                Tags = request.GetTags(),
-                OfficialRatings = request.GetOfficialRatings(),
-                Genres = request.GetGenres(),
-                ArtistIds = GetGuids(request.ArtistIds),
-                AlbumArtistIds = GetGuids(request.AlbumArtistIds),
-                ContributingArtistIds = GetGuids(request.ContributingArtistIds),
-                GenreIds = GetGuids(request.GenreIds),
-                StudioIds = GetGuids(request.StudioIds),
-                Person = request.Person,
-                PersonIds = GetGuids(request.PersonIds),
-                PersonTypes = request.GetPersonTypes(),
-                Years = request.GetYears(),
-                ImageTypes = request.GetImageTypes(),
-                VideoTypes = request.GetVideoTypes(),
-                AdjacentTo = request.AdjacentTo,
-                ItemIds = GetGuids(request.Ids),
-                MinCommunityRating = request.MinCommunityRating,
-                MinCriticRating = request.MinCriticRating,
-                ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId),
-                ParentIndexNumber = request.ParentIndexNumber,
-                EnableTotalRecordCount = request.EnableTotalRecordCount,
-                ExcludeItemIds = GetGuids(request.ExcludeItemIds),
-                DtoOptions = dtoOptions,
-                SearchTerm = request.SearchTerm
-            };
-
-            if (!string.IsNullOrWhiteSpace(request.Ids) || !string.IsNullOrWhiteSpace(request.SearchTerm))
-            {
-                query.CollapseBoxSetItems = false;
-            }
-
-            foreach (var filter in request.GetFilters())
-            {
-                switch (filter)
-                {
-                    case ItemFilter.Dislikes:
-                        query.IsLiked = false;
-                        break;
-                    case ItemFilter.IsFavorite:
-                        query.IsFavorite = true;
-                        break;
-                    case ItemFilter.IsFavoriteOrLikes:
-                        query.IsFavoriteOrLiked = true;
-                        break;
-                    case ItemFilter.IsFolder:
-                        query.IsFolder = true;
-                        break;
-                    case ItemFilter.IsNotFolder:
-                        query.IsFolder = false;
-                        break;
-                    case ItemFilter.IsPlayed:
-                        query.IsPlayed = true;
-                        break;
-                    case ItemFilter.IsResumable:
-                        query.IsResumable = true;
-                        break;
-                    case ItemFilter.IsUnplayed:
-                        query.IsPlayed = false;
-                        break;
-                    case ItemFilter.Likes:
-                        query.IsLiked = true;
-                        break;
-                }
-            }
-
-            if (!string.IsNullOrEmpty(request.MinDateLastSaved))
-            {
-                query.MinDateLastSaved = DateTime.Parse(request.MinDateLastSaved, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MinDateLastSavedForUser))
-            {
-                query.MinDateLastSavedForUser = DateTime.Parse(request.MinDateLastSavedForUser, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MinPremiereDate))
-            {
-                query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            if (!string.IsNullOrEmpty(request.MaxPremiereDate))
-            {
-                query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-            }
-
-            // Filter by Series Status
-            if (!string.IsNullOrEmpty(request.SeriesStatus))
-            {
-                query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
-            }
-
-            // ExcludeLocationTypes
-            if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
-            {
-                var excludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
-                if (excludeLocationTypes.Contains(LocationType.Virtual))
-                {
-                    query.IsVirtualItem = false;
-                }
-            }
-
-            if (!string.IsNullOrEmpty(request.LocationTypes))
-            {
-                var requestedLocationTypes =
-                    request.LocationTypes.Split(',');
-
-                if (requestedLocationTypes.Length > 0 && requestedLocationTypes.Length < 4)
-                {
-                    query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual.ToString());
-                }
-            }
-
-            // Min official rating
-            if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
-            {
-                query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
-            }
-
-            // Max official rating
-            if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating))
-            {
-                query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating);
-            }
-
-            // Artists
-            if (!string.IsNullOrEmpty(request.Artists))
-            {
-                query.ArtistIds = request.Artists.Split('|').Select(i =>
-                {
-                    try
-                    {
-                        return _libraryManager.GetArtist(i, new DtoOptions(false));
-                    }
-                    catch
-                    {
-                        return null;
-                    }
-                }).Where(i => i != null).Select(i => i.Id).ToArray();
-            }
-
-            // ExcludeArtistIds
-            if (!string.IsNullOrWhiteSpace(request.ExcludeArtistIds))
-            {
-                query.ExcludeArtistIds = GetGuids(request.ExcludeArtistIds);
-            }
-
-            if (!string.IsNullOrWhiteSpace(request.AlbumIds))
-            {
-                query.AlbumIds = GetGuids(request.AlbumIds);
-            }
-
-            // Albums
-            if (!string.IsNullOrEmpty(request.Albums))
-            {
-                query.AlbumIds = request.Albums.Split('|').SelectMany(i =>
-                {
-                    return _libraryManager.GetItemIds(new InternalItemsQuery
-                    {
-                        IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
-                        Name = i,
-                        Limit = 1
-                    });
-                }).ToArray();
-            }
-
-            // Studios
-            if (!string.IsNullOrEmpty(request.Studios))
-            {
-                query.StudioIds = request.Studios.Split('|').Select(i =>
-                {
-                    try
-                    {
-                        return _libraryManager.GetStudio(i);
-                    }
-                    catch
-                    {
-                        return null;
-                    }
-                }).Where(i => i != null).Select(i => i.Id).ToArray();
-            }
-
-            // Apply default sorting if none requested
-            if (query.OrderBy.Count == 0)
-            {
-                // Albums by artist
-                if (query.ArtistIds.Length > 0 && query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], "MusicAlbum", StringComparison.OrdinalIgnoreCase))
-                {
-                    query.OrderBy = new[]
-                    {
-                        new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending),
-                        new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending)
-                    };
-                }
-            }
-
-            return query;
-        }
-    }
-
-    /// <summary>
-    /// Class DateCreatedComparer.
-    /// </summary>
-    public class DateCreatedComparer : IComparer<BaseItem>
-    {
-        /// <summary>
-        /// Compares the specified x.
-        /// </summary>
-        /// <param name="x">The x.</param>
-        /// <param name="y">The y.</param>
-        /// <returns>System.Int32.</returns>
-        public int Compare(BaseItem x, BaseItem y)
-        {
-            return x.DateCreated.CompareTo(y.DateCreated);
-        }
-    }
-}

+ 0 - 146
MediaBrowser.Api/UserLibrary/PersonsService.cs

@@ -1,146 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetPersons.
-    /// </summary>
-    [Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
-    public class GetPersons : GetItemsByName
-    {
-    }
-
-    /// <summary>
-    /// Class GetPerson.
-    /// </summary>
-    [Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")]
-    public class GetPerson : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The person name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class PersonsService.
-    /// </summary>
-    [Authenticated]
-    public class PersonsService : BaseItemsByNameService<Person>
-    {
-        public PersonsService(
-            ILogger<PersonsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(
-                logger,
-                serverConfigurationManager,
-                httpResultFactory,
-                userManager,
-                libraryManager,
-                userDataRepository,
-                dtoService,
-                authorizationContext)
-        {
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPerson request)
-        {
-            var result = GetItem(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the item.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto}.</returns>
-        private BaseItemDto GetItem(GetPerson request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            var item = GetPerson(request.Name, LibraryManager, dtoOptions);
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-
-                return DtoService.GetBaseItemDto(item, dtoOptions, user);
-            }
-
-            return DtoService.GetBaseItemDto(item, dtoOptions);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetPersons request)
-        {
-            return GetResultSlim(request);
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
-        protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
-        {
-            throw new NotImplementedException();
-        }
-
-        protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
-        {
-            var items = LibraryManager.GetPeopleItems(new InternalPeopleQuery
-            {
-                PersonTypes = query.PersonTypes,
-                NameContains = query.NameContains ?? query.SearchTerm
-            });
-
-            if ((query.IsFavorite ?? false) && query.User != null)
-            {
-                items = items.Where(i => UserDataRepository.GetUserData(query.User, i).IsFavorite).ToList();
-            }
-
-            return new QueryResult<(BaseItem, ItemCounts)>
-            {
-                TotalRecordCount = items.Count,
-                Items = items.Take(query.Limit ?? int.MaxValue).Select(i => (i as BaseItem, new ItemCounts())).ToArray()
-            };
-        }
-    }
-}

+ 0 - 456
MediaBrowser.Api/UserLibrary/PlaystateService.cs

@@ -1,456 +0,0 @@
-using System;
-using System.Globalization;
-using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Session;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class MarkPlayedItem.
-    /// </summary>
-    [Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")]
-    public class MarkPlayedItem : IReturn<UserItemDataDto>
-    {
-        /// <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 string UserId { get; set; }
-
-        [ApiMember(Name = "DatePlayed", Description = "The date the item was played (if any). Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string DatePlayed { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class MarkUnplayedItem.
-    /// </summary>
-    [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")]
-    public class MarkUnplayedItem : IReturn<UserItemDataDto>
-    {
-        /// <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 string UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Sessions/Playing", "POST", Summary = "Reports playback has started within a session")]
-    public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
-    {
-    }
-
-    [Route("/Sessions/Playing/Progress", "POST", Summary = "Reports playback progress within a session")]
-    public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
-    {
-    }
-
-    [Route("/Sessions/Playing/Ping", "POST", Summary = "Pings a playback session")]
-    public class PingPlaybackSession : IReturnVoid
-    {
-        [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string PlaySessionId { get; set; }
-    }
-
-    [Route("/Sessions/Playing/Stopped", "POST", Summary = "Reports playback has stopped within a session")]
-    public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
-    {
-    }
-
-    /// <summary>
-    /// Class OnPlaybackStart.
-    /// </summary>
-    [Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")]
-    public class OnPlaybackStart : 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 string UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string MediaSourceId { get; set; }
-
-        [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
-        public bool CanSeek { get; set; }
-
-        [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int? AudioStreamIndex { get; set; }
-
-        [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int? SubtitleStreamIndex { get; set; }
-
-        [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public PlayMethod PlayMethod { get; set; }
-
-        [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string LiveStreamId { get; set; }
-
-        [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string PlaySessionId { get; set; }
-    }
-
-    /// <summary>
-    /// Class OnPlaybackProgress.
-    /// </summary>
-    [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")]
-    public class OnPlaybackProgress : 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 string UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string MediaSourceId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the position ticks.
-        /// </summary>
-        /// <value>The position ticks.</value>
-        [ApiMember(Name = "PositionTicks", Description = "Optional. The current position, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public long? PositionTicks { get; set; }
-
-        [ApiMember(Name = "IsPaused", Description = "Indicates if the player is paused.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
-        public bool IsPaused { get; set; }
-
-        [ApiMember(Name = "IsMuted", Description = "Indicates if the player is muted.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
-        public bool IsMuted { get; set; }
-
-        [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int? AudioStreamIndex { get; set; }
-
-        [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int? SubtitleStreamIndex { get; set; }
-
-        [ApiMember(Name = "VolumeLevel", Description = "Scale of 0-100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int? VolumeLevel { get; set; }
-
-        [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public PlayMethod PlayMethod { get; set; }
-
-        [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string LiveStreamId { get; set; }
-
-        [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string PlaySessionId { get; set; }
-
-        [ApiMember(Name = "RepeatMode", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public RepeatMode RepeatMode { get; set; }
-    }
-
-    /// <summary>
-    /// Class OnPlaybackStopped.
-    /// </summary>
-    [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")]
-    public class OnPlaybackStopped : 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 string UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-
-        [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string MediaSourceId { get; set; }
-
-        [ApiMember(Name = "NextMediaType", Description = "The next media type that will play", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
-        public string NextMediaType { get; set; }
-
-        /// <summary>
-        /// Gets or sets the position ticks.
-        /// </summary>
-        /// <value>The position ticks.</value>
-        [ApiMember(Name = "PositionTicks", Description = "Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "DELETE")]
-        public long? PositionTicks { get; set; }
-
-        [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string LiveStreamId { get; set; }
-
-        [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string PlaySessionId { get; set; }
-    }
-
-    [Authenticated]
-    public class PlaystateService : BaseApiService
-    {
-        private readonly IUserManager _userManager;
-        private readonly IUserDataManager _userDataRepository;
-        private readonly ILibraryManager _libraryManager;
-        private readonly ISessionManager _sessionManager;
-        private readonly ISessionContext _sessionContext;
-        private readonly IAuthorizationContext _authContext;
-
-        public PlaystateService(
-            ILogger<PlaystateService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            IUserDataManager userDataRepository,
-            ILibraryManager libraryManager,
-            ISessionManager sessionManager,
-            ISessionContext sessionContext,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _userDataRepository = userDataRepository;
-            _libraryManager = libraryManager;
-            _sessionManager = sessionManager;
-            _sessionContext = sessionContext;
-            _authContext = authContext;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Post(MarkPlayedItem request)
-        {
-            var result = MarkPlayed(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        private UserItemDataDto MarkPlayed(MarkPlayedItem request)
-        {
-            var user = _userManager.GetUserById(Guid.Parse(request.UserId));
-
-            DateTime? datePlayed = null;
-
-            if (!string.IsNullOrEmpty(request.DatePlayed))
-            {
-                datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
-            }
-
-            var session = GetSession(_sessionContext);
-
-            var dto = UpdatePlayedStatus(user, request.Id, true, datePlayed);
-
-            foreach (var additionalUserInfo in session.AdditionalUsers)
-            {
-                var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
-
-                UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed);
-            }
-
-            return dto;
-        }
-
-        private PlayMethod ValidatePlayMethod(PlayMethod method, string playSessionId)
-        {
-            if (method == PlayMethod.Transcode)
-            {
-                var job = string.IsNullOrWhiteSpace(playSessionId) ? null : ApiEntryPoint.Instance.GetTranscodingJob(playSessionId);
-                if (job == null)
-                {
-                    return PlayMethod.DirectPlay;
-                }
-            }
-
-            return method;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(OnPlaybackStart request)
-        {
-            Post(new ReportPlaybackStart
-            {
-                CanSeek = request.CanSeek,
-                ItemId = new Guid(request.Id),
-                MediaSourceId = request.MediaSourceId,
-                AudioStreamIndex = request.AudioStreamIndex,
-                SubtitleStreamIndex = request.SubtitleStreamIndex,
-                PlayMethod = request.PlayMethod,
-                PlaySessionId = request.PlaySessionId,
-                LiveStreamId = request.LiveStreamId
-            });
-        }
-
-        public void Post(ReportPlaybackStart request)
-        {
-            request.PlayMethod = ValidatePlayMethod(request.PlayMethod, request.PlaySessionId);
-
-            request.SessionId = GetSession(_sessionContext).Id;
-
-            var task = _sessionManager.OnPlaybackStart(request);
-
-            Task.WaitAll(task);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public void Post(OnPlaybackProgress request)
-        {
-            Post(new ReportPlaybackProgress
-            {
-                ItemId = new Guid(request.Id),
-                PositionTicks = request.PositionTicks,
-                IsMuted = request.IsMuted,
-                IsPaused = request.IsPaused,
-                MediaSourceId = request.MediaSourceId,
-                AudioStreamIndex = request.AudioStreamIndex,
-                SubtitleStreamIndex = request.SubtitleStreamIndex,
-                VolumeLevel = request.VolumeLevel,
-                PlayMethod = request.PlayMethod,
-                PlaySessionId = request.PlaySessionId,
-                LiveStreamId = request.LiveStreamId,
-                RepeatMode = request.RepeatMode
-            });
-        }
-
-        public void Post(ReportPlaybackProgress request)
-        {
-            request.PlayMethod = ValidatePlayMethod(request.PlayMethod, request.PlaySessionId);
-
-            request.SessionId = GetSession(_sessionContext).Id;
-
-            var task = _sessionManager.OnPlaybackProgress(request);
-
-            Task.WaitAll(task);
-        }
-
-        public void Post(PingPlaybackSession request)
-        {
-            ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId, null);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Delete(OnPlaybackStopped request)
-        {
-            return Post(new ReportPlaybackStopped
-            {
-                ItemId = new Guid(request.Id),
-                PositionTicks = request.PositionTicks,
-                MediaSourceId = request.MediaSourceId,
-                PlaySessionId = request.PlaySessionId,
-                LiveStreamId = request.LiveStreamId,
-                NextMediaType = request.NextMediaType
-            });
-        }
-
-        public async Task Post(ReportPlaybackStopped request)
-        {
-            Logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", request.PlaySessionId ?? string.Empty);
-
-            if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
-            {
-                await ApiEntryPoint.Instance.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true);
-            }
-
-            request.SessionId = GetSession(_sessionContext).Id;
-
-            await _sessionManager.OnPlaybackStopped(request);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Delete(MarkUnplayedItem request)
-        {
-            var task = MarkUnplayed(request);
-
-            return ToOptimizedResult(task);
-        }
-
-        private UserItemDataDto MarkUnplayed(MarkUnplayedItem request)
-        {
-            var user = _userManager.GetUserById(Guid.Parse(request.UserId));
-
-            var session = GetSession(_sessionContext);
-
-            var dto = UpdatePlayedStatus(user, request.Id, false, null);
-
-            foreach (var additionalUserInfo in session.AdditionalUsers)
-            {
-                var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
-
-                UpdatePlayedStatus(additionalUser, request.Id, false, null);
-            }
-
-            return dto;
-        }
-
-        /// <summary>
-        /// Updates the played status.
-        /// </summary>
-        /// <param name="user">The user.</param>
-        /// <param name="itemId">The item id.</param>
-        /// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
-        /// <param name="datePlayed">The date played.</param>
-        /// <returns>Task.</returns>
-        private UserItemDataDto UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed)
-        {
-            var item = _libraryManager.GetItemById(itemId);
-
-            if (wasPlayed)
-            {
-                item.MarkPlayed(user, datePlayed, true);
-            }
-            else
-            {
-                item.MarkUnplayed(user);
-            }
-
-            return _userDataRepository.GetUserDataDto(item, user);
-        }
-    }
-}

+ 0 - 132
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -1,132 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetStudios.
-    /// </summary>
-    [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
-    public class GetStudios : GetItemsByName
-    {
-    }
-
-    /// <summary>
-    /// Class GetStudio.
-    /// </summary>
-    [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
-    public class GetStudio : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        [ApiMember(Name = "Name", Description = "The studio name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class StudiosService.
-    /// </summary>
-    [Authenticated]
-    public class StudiosService : BaseItemsByNameService<Studio>
-    {
-        public StudiosService(
-            ILogger<StudiosService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(
-                logger,
-                serverConfigurationManager,
-                httpResultFactory,
-                userManager,
-                libraryManager,
-                userDataRepository,
-                dtoService,
-                authorizationContext)
-        {
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetStudio request)
-        {
-            var result = GetItem(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the item.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto}.</returns>
-        private BaseItemDto GetItem(GetStudio request)
-        {
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            var item = GetStudio(request.Name, LibraryManager, dtoOptions);
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-
-                return DtoService.GetBaseItemDto(item, dtoOptions, user);
-            }
-
-            return DtoService.GetBaseItemDto(item, dtoOptions);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetStudios request)
-        {
-            var result = GetResultSlim(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
-        {
-            return LibraryManager.GetStudios(query);
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
-        protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}

+ 0 - 575
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -1,575 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetItem.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")]
-    public class GetItem : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetItem.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")]
-    public class GetRootFolder : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetIntros.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")]
-    public class GetIntros : IReturn<QueryResult<BaseItemDto>>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the item id.
-        /// </summary>
-        /// <value>The item id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class MarkFavoriteItem.
-    /// </summary>
-    [Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")]
-    public class MarkFavoriteItem : IReturn<UserItemDataDto>
-    {
-        /// <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 id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UnmarkFavoriteItem.
-    /// </summary>
-    [Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")]
-    public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
-    {
-        /// <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 id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class ClearUserItemRating.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")]
-    public class DeleteUserItemRating : IReturn<UserItemDataDto>
-    {
-        /// <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 id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateUserItemRating.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")]
-    public class UpdateUserItemRating : IReturn<UserItemDataDto>
-    {
-        /// <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 id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether this <see cref="UpdateUserItemRating" /> is likes.
-        /// </summary>
-        /// <value><c>true</c> if likes; otherwise, <c>false</c>.</value>
-        [ApiMember(Name = "Likes", Description = "Whether the user likes the item or not. true/false", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
-        public bool Likes { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetLocalTrailers.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")]
-    public class GetLocalTrailers : IReturn<BaseItemDto[]>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetSpecialFeatures.
-    /// </summary>
-    [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")]
-    public class GetSpecialFeatures : IReturn<BaseItemDto[]>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", Description = "Movie Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    [Route("/Users/{UserId}/Items/Latest", "GET", Summary = "Gets latest media")]
-    public class GetLatestMedia : IReturn<BaseItemDto[]>, IHasDtoOptions
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "Limit", Description = "Limit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int Limit { get; set; }
-
-        [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid ParentId { get; set; }
-
-        [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string Fields { get; set; }
-
-        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
-        public string IncludeItemTypes { get; set; }
-
-        [ApiMember(Name = "IsFolder", Description = "Filter by items that are folders, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsFolder { get; set; }
-
-        [ApiMember(Name = "IsPlayed", Description = "Filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsPlayed { get; set; }
-
-        [ApiMember(Name = "GroupItems", Description = "Whether or not to group items into a parent container.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool GroupItems { get; set; }
-
-        [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableImages { get; set; }
-
-        [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int? ImageTypeLimit { get; set; }
-
-        [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string EnableImageTypes { get; set; }
-
-        [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? EnableUserData { get; set; }
-
-        public GetLatestMedia()
-        {
-            Limit = 20;
-            GroupItems = true;
-        }
-    }
-
-    /// <summary>
-    /// Class UserLibraryService.
-    /// </summary>
-    [Authenticated]
-    public class UserLibraryService : BaseApiService
-    {
-        private readonly IUserManager _userManager;
-        private readonly IUserDataManager _userDataRepository;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IDtoService _dtoService;
-        private readonly IUserViewManager _userViewManager;
-        private readonly IFileSystem _fileSystem;
-        private readonly IAuthorizationContext _authContext;
-
-        public UserLibraryService(
-            ILogger<UserLibraryService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IUserViewManager userViewManager,
-            IFileSystem fileSystem,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
-            _userDataRepository = userDataRepository;
-            _dtoService = dtoService;
-            _userViewManager = userViewManager;
-            _fileSystem = fileSystem;
-            _authContext = authContext;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetSpecialFeatures request)
-        {
-            var result = GetAsync(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetLatestMedia request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            if (!request.IsPlayed.HasValue)
-            {
-                if (user.HidePlayedInLatest)
-                {
-                    request.IsPlayed = false;
-                }
-            }
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var list = _userViewManager.GetLatestItems(new LatestItemsQuery
-            {
-                GroupItems = request.GroupItems,
-                IncludeItemTypes = ApiEntryPoint.Split(request.IncludeItemTypes, ',', true),
-                IsPlayed = request.IsPlayed,
-                Limit = request.Limit,
-                ParentId = request.ParentId,
-                UserId = request.UserId,
-            }, dtoOptions);
-
-            var dtos = list.Select(i =>
-            {
-                var item = i.Item2[0];
-                var childCount = 0;
-
-                if (i.Item1 != null && (i.Item2.Count > 1 || i.Item1 is MusicAlbum))
-                {
-                    item = i.Item1;
-                    childCount = i.Item2.Count;
-                }
-
-                var dto = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
-                dto.ChildCount = childCount;
-
-                return dto;
-            });
-
-            return ToOptimizedResult(dtos.ToArray());
-        }
-
-        private BaseItemDto[] GetAsync(GetSpecialFeatures request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ?
-                _libraryManager.GetUserRootFolder() :
-                _libraryManager.GetItemById(request.Id);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var dtos = item
-                .GetExtras(BaseItem.DisplayExtraTypes)
-                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
-
-            return dtos.ToArray();
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetLocalTrailers request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer })
-                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
-                .ToArray();
-
-            if (item is IHasTrailers hasTrailers)
-            {
-                var trailers = hasTrailers.GetTrailers();
-                var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item);
-                var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count];
-                dtosExtras.CopyTo(allTrailers, 0);
-                dtosTrailers.CopyTo(allTrailers, dtosExtras.Length);
-                return ToOptimizedResult(allTrailers);
-            }
-
-            return ToOptimizedResult(dtosExtras);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Get(GetItem request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
-            await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
-            return ToOptimizedResult(result);
-        }
-
-        private async Task RefreshItemOnDemandIfNeeded(BaseItem item)
-        {
-            if (item is Person)
-            {
-                var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary);
-                var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 3;
-
-                if (!hasMetdata)
-                {
-                    var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem))
-                    {
-                        MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
-                        ImageRefreshMode = MetadataRefreshMode.FullRefresh,
-                        ForceSave = performFullRefresh
-                    };
-
-                    await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetRootFolder request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = _libraryManager.GetUserRootFolder();
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Get(GetIntros request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
-            var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-
-            var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = dtos,
-                TotalRecordCount = dtos.Length
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Post(MarkFavoriteItem request)
-        {
-            var dto = MarkFavorite(request.UserId, request.Id, true);
-
-            return ToOptimizedResult(dto);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Delete(UnmarkFavoriteItem request)
-        {
-            var dto = MarkFavorite(request.UserId, request.Id, false);
-
-            return ToOptimizedResult(dto);
-        }
-
-        /// <summary>
-        /// Marks the favorite.
-        /// </summary>
-        /// <param name="userId">The user id.</param>
-        /// <param name="itemId">The item id.</param>
-        /// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
-        private UserItemDataDto MarkFavorite(Guid userId, Guid itemId, bool isFavorite)
-        {
-            var user = _userManager.GetUserById(userId);
-
-            var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
-            // Get the user data for this item
-            var data = _userDataRepository.GetUserData(user, item);
-
-            // Set favorite status
-            data.IsFavorite = isFavorite;
-
-            _userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
-
-            return _userDataRepository.GetUserDataDto(item, user);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Delete(DeleteUserItemRating request)
-        {
-            var dto = UpdateUserItemRating(request.UserId, request.Id, null);
-
-            return ToOptimizedResult(dto);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Post(UpdateUserItemRating request)
-        {
-            var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes);
-
-            return ToOptimizedResult(dto);
-        }
-
-        /// <summary>
-        /// Updates the user item rating.
-        /// </summary>
-        /// <param name="userId">The user id.</param>
-        /// <param name="itemId">The item id.</param>
-        /// <param name="likes">if set to <c>true</c> [likes].</param>
-        private UserItemDataDto UpdateUserItemRating(Guid userId, Guid itemId, bool? likes)
-        {
-            var user = _userManager.GetUserById(userId);
-
-            var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
-            // Get the user data for this item
-            var data = _userDataRepository.GetUserData(user, item);
-
-            data.Likes = likes;
-
-            _userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
-
-            return _userDataRepository.GetUserDataDto(item, user);
-        }
-    }
-}

+ 0 - 148
MediaBrowser.Api/UserLibrary/UserViewsService.cs

@@ -1,148 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Library;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    [Route("/Users/{UserId}/Views", "GET")]
-    public class GetUserViews : IReturn<QueryResult<BaseItemDto>>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-
-        [ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "GET")]
-        public bool? IncludeExternalContent { get; set; }
-
-        public bool IncludeHidden { get; set; }
-
-        public string PresetViews { get; set; }
-    }
-
-    [Route("/Users/{UserId}/GroupingOptions", "GET")]
-    public class GetGroupingOptions : IReturn<SpecialViewOption[]>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    public class UserViewsService : BaseApiService
-    {
-        private readonly IUserManager _userManager;
-        private readonly IUserViewManager _userViewManager;
-        private readonly IDtoService _dtoService;
-        private readonly IAuthorizationContext _authContext;
-        private readonly ILibraryManager _libraryManager;
-
-        public UserViewsService(
-            ILogger<UserViewsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            IUserViewManager userViewManager,
-            IDtoService dtoService,
-            IAuthorizationContext authContext,
-            ILibraryManager libraryManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _userViewManager = userViewManager;
-            _dtoService = dtoService;
-            _authContext = authContext;
-            _libraryManager = libraryManager;
-        }
-
-        public object Get(GetUserViews request)
-        {
-            var query = new UserViewQuery
-            {
-                UserId = request.UserId
-            };
-
-            if (request.IncludeExternalContent.HasValue)
-            {
-                query.IncludeExternalContent = request.IncludeExternalContent.Value;
-            }
-
-            query.IncludeHidden = request.IncludeHidden;
-
-            if (!string.IsNullOrWhiteSpace(request.PresetViews))
-            {
-                query.PresetViews = request.PresetViews.Split(',');
-            }
-
-            var app = _authContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
-            if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
-            {
-                query.PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows };
-            }
-
-            var folders = _userViewManager.GetUserViews(query);
-
-            var dtoOptions = GetDtoOptions(_authContext, request);
-            var fields = dtoOptions.Fields.ToList();
-
-            fields.Add(ItemFields.PrimaryImageAspectRatio);
-            fields.Add(ItemFields.DisplayPreferencesId);
-            fields.Remove(ItemFields.BasicSyncInfo);
-            dtoOptions.Fields = fields.ToArray();
-
-            var user = _userManager.GetUserById(request.UserId);
-
-            var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
-                .ToArray();
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = dtos,
-                TotalRecordCount = dtos.Length
-            };
-
-            return ToOptimizedResult(result);
-        }
-
-        public object Get(GetGroupingOptions request)
-        {
-            var user = _userManager.GetUserById(request.UserId);
-
-            var list = _libraryManager.GetUserRootFolder()
-                .GetChildren(user, true)
-                .OfType<Folder>()
-                .Where(UserView.IsEligibleForGrouping)
-                .Select(i => new SpecialViewOption
-                {
-                    Name = i.Name,
-                    Id = i.Id.ToString("N", CultureInfo.InvariantCulture)
-                })
-            .OrderBy(i => i.Name)
-            .ToArray();
-
-            return ToOptimizedResult(list);
-        }
-    }
-
-    class SpecialViewOption
-    {
-        public string Name { get; set; }
-
-        public string Id { get; set; }
-    }
-}

+ 0 - 131
MediaBrowser.Api/UserLibrary/YearsService.cs

@@ -1,131 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
-    /// <summary>
-    /// Class GetYears.
-    /// </summary>
-    [Route("/Years", "GET", Summary = "Gets all years from a given item, folder, or the entire library")]
-    public class GetYears : GetItemsByName
-    {
-    }
-
-    /// <summary>
-    /// Class GetYear.
-    /// </summary>
-    [Route("/Years/{Year}", "GET", Summary = "Gets a year")]
-    public class GetYear : IReturn<BaseItemDto>
-    {
-        /// <summary>
-        /// Gets or sets the year.
-        /// </summary>
-        /// <value>The year.</value>
-        [ApiMember(Name = "Year", Description = "The year", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
-        public int Year { get; set; }
-
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public Guid UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class YearsService.
-    /// </summary>
-    [Authenticated]
-    public class YearsService : BaseItemsByNameService<Year>
-    {
-        public YearsService(
-            ILogger<YearsService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ILibraryManager libraryManager,
-            IUserDataManager userDataRepository,
-            IDtoService dtoService,
-            IAuthorizationContext authorizationContext)
-            : base(
-                logger,
-                serverConfigurationManager,
-                httpResultFactory,
-                userManager,
-                libraryManager,
-                userDataRepository,
-                dtoService,
-                authorizationContext)
-        {
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetYear request)
-        {
-            var result = GetItem(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the item.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{BaseItemDto}.</returns>
-        private BaseItemDto GetItem(GetYear request)
-        {
-            var item = LibraryManager.GetYear(request.Year);
-
-            var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
-            if (!request.UserId.Equals(Guid.Empty))
-            {
-                var user = UserManager.GetUserById(request.UserId);
-
-                return DtoService.GetBaseItemDto(item, dtoOptions, user);
-            }
-
-            return DtoService.GetBaseItemDto(item, dtoOptions);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetYears request)
-        {
-            var result = GetResult(request);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets all items.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <param name="items">The items.</param>
-        /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
-        protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
-        {
-            return items
-                .Select(i => i.ProductionYear ?? 0)
-                .Where(i => i > 0)
-                .Distinct()
-                .Select(year => LibraryManager.GetYear(year));
-        }
-    }
-}

+ 0 - 598
MediaBrowser.Api/UserService.cs

@@ -1,598 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Authentication;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Users;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class GetUsers.
-    /// </summary>
-    [Route("/Users", "GET", Summary = "Gets a list of users")]
-    [Authenticated]
-    public class GetUsers : IReturn<UserDto[]>
-    {
-        [ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsHidden { get; set; }
-
-        [ApiMember(Name = "IsDisabled", Description = "Optional filter by IsDisabled=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsDisabled { get; set; }
-
-        [ApiMember(Name = "IsGuest", Description = "Optional filter by IsGuest=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsGuest { get; set; }
-    }
-
-    [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
-    public class GetPublicUsers : IReturn<UserDto[]>
-    {
-    }
-
-    /// <summary>
-    /// Class GetUser.
-    /// </summary>
-    [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
-    [Authenticated(EscapeParentalControl = true)]
-    public class GetUser : IReturn<UserDto>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class DeleteUser.
-    /// </summary>
-    [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
-    [Authenticated(Roles = "Admin")]
-    public class DeleteUser : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class AuthenticateUser.
-    /// </summary>
-    [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")]
-    public class AuthenticateUser : IReturn<AuthenticationResult>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-
-        [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Pw { get; set; }
-
-        /// <summary>
-        /// Gets or sets the password.
-        /// </summary>
-        /// <value>The password.</value>
-        [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Password { get; set; }
-    }
-
-    /// <summary>
-    /// Class AuthenticateUser.
-    /// </summary>
-    [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")]
-    public class AuthenticateUserByName : IReturn<AuthenticationResult>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Username", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Username { get; set; }
-
-        /// <summary>
-        /// Gets or sets the password.
-        /// </summary>
-        /// <value>The password.</value>
-        [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Password { get; set; }
-
-        [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Pw { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateUserPassword.
-    /// </summary>
-    [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")]
-    [Authenticated]
-    public class UpdateUserPassword : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        public Guid Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the password.
-        /// </summary>
-        /// <value>The password.</value>
-        public string CurrentPassword { get; set; }
-
-        public string CurrentPw { get; set; }
-
-        public string NewPw { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [reset password].
-        /// </summary>
-        /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
-        public bool ResetPassword { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateUserEasyPassword.
-    /// </summary>
-    [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")]
-    [Authenticated]
-    public class UpdateUserEasyPassword : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        public Guid Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the new password.
-        /// </summary>
-        /// <value>The new password.</value>
-        public string NewPassword { get; set; }
-
-        public string NewPw { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether [reset password].
-        /// </summary>
-        /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
-        public bool ResetPassword { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateUser.
-    /// </summary>
-    [Route("/Users/{Id}", "POST", Summary = "Updates a user")]
-    [Authenticated]
-    public class UpdateUser : UserDto, IReturnVoid
-    {
-    }
-
-    /// <summary>
-    /// Class UpdateUser.
-    /// </summary>
-    [Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")]
-    [Authenticated(Roles = "admin")]
-    public class UpdateUserPolicy : UserPolicy, IReturnVoid
-    {
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateUser.
-    /// </summary>
-    [Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")]
-    [Authenticated]
-    public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
-    {
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public Guid Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class CreateUser.
-    /// </summary>
-    [Route("/Users/New", "POST", Summary = "Creates a user")]
-    [Authenticated(Roles = "Admin")]
-    public class CreateUserByName : IReturn<UserDto>
-    {
-        [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Name { get; set; }
-
-        [ApiMember(Name = "Password", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Password { get; set; }
-    }
-
-    [Route("/Users/ForgotPassword", "POST", Summary = "Initiates the forgot password process for a local user")]
-    public class ForgotPassword : IReturn<ForgotPasswordResult>
-    {
-        [ApiMember(Name = "EnteredUsername", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string EnteredUsername { get; set; }
-    }
-
-    [Route("/Users/ForgotPassword/Pin", "POST", Summary = "Redeems a forgot password pin")]
-    public class ForgotPasswordPin : IReturn<PinRedeemResult>
-    {
-        [ApiMember(Name = "Pin", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
-        public string Pin { get; set; }
-    }
-
-    /// <summary>
-    /// Class UsersService.
-    /// </summary>
-    public class UserService : BaseApiService
-    {
-        /// <summary>
-        /// The user manager.
-        /// </summary>
-        private readonly IUserManager _userManager;
-        private readonly ISessionManager _sessionMananger;
-        private readonly INetworkManager _networkManager;
-        private readonly IDeviceManager _deviceManager;
-        private readonly IAuthorizationContext _authContext;
-
-        public UserService(
-            ILogger<UserService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            IUserManager userManager,
-            ISessionManager sessionMananger,
-            INetworkManager networkManager,
-            IDeviceManager deviceManager,
-            IAuthorizationContext authContext)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _userManager = userManager;
-            _sessionMananger = sessionMananger;
-            _networkManager = networkManager;
-            _deviceManager = deviceManager;
-            _authContext = authContext;
-        }
-
-        public object Get(GetPublicUsers request)
-        {
-            // If the startup wizard hasn't been completed then just return all users
-            if (!ServerConfigurationManager.Configuration.IsStartupWizardCompleted)
-            {
-                return Get(new GetUsers
-                {
-                    IsDisabled = false
-                });
-            }
-
-            return Get(new GetUsers
-            {
-                IsHidden = false,
-                IsDisabled = false
-            }, true, true);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetUsers request)
-        {
-            return Get(request, false, false);
-        }
-
-        private object Get(GetUsers request, bool filterByDevice, bool filterByNetwork)
-        {
-            var users = _userManager.Users;
-
-            if (request.IsDisabled.HasValue)
-            {
-                users = users.Where(i => i.HasPermission(PermissionKind.IsDisabled) == request.IsDisabled.Value);
-            }
-
-            if (request.IsHidden.HasValue)
-            {
-                users = users.Where(i => i.HasPermission(PermissionKind.IsHidden) == request.IsHidden.Value);
-            }
-
-            if (filterByDevice)
-            {
-                var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
-
-                if (!string.IsNullOrWhiteSpace(deviceId))
-                {
-                    users = users.Where(i => _deviceManager.CanAccessDevice(i, deviceId));
-                }
-            }
-
-            if (filterByNetwork)
-            {
-                if (!_networkManager.IsInLocalNetwork(Request.RemoteIp))
-                {
-                    users = users.Where(i => i.HasPermission(PermissionKind.EnableRemoteAccess));
-                }
-            }
-
-            var result = users
-                .OrderBy(u => u.Username)
-                .Select(i => _userManager.GetUserDto(i, Request.RemoteIp))
-                .ToArray();
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetUser request)
-        {
-            var user = _userManager.GetUserById(request.Id);
-
-            if (user == null)
-            {
-                throw new ResourceNotFoundException("User not found");
-            }
-
-            var result = _userManager.GetUserDto(user, Request.RemoteIp);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Deletes the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Delete(DeleteUser request)
-        {
-            return DeleteAsync(request);
-        }
-
-        public Task DeleteAsync(DeleteUser request)
-        {
-            _userManager.DeleteUser(request.Id);
-            _sessionMananger.RevokeUserTokens(request.Id, null);
-            return Task.CompletedTask;
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public object Post(AuthenticateUser request)
-        {
-            var user = _userManager.GetUserById(request.Id);
-
-            if (user == null)
-            {
-                throw new ResourceNotFoundException("User not found");
-            }
-
-            if (!string.IsNullOrEmpty(request.Password) && string.IsNullOrEmpty(request.Pw))
-            {
-                throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API.");
-            }
-
-            // Password should always be null
-            return Post(new AuthenticateUserByName
-            {
-                Username = user.Username,
-                Password = null,
-                Pw = request.Pw
-            });
-        }
-
-        public async Task<object> Post(AuthenticateUserByName request)
-        {
-            var auth = _authContext.GetAuthorizationInfo(Request);
-
-            try
-            {
-                var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest
-                {
-                    App = auth.Client,
-                    AppVersion = auth.Version,
-                    DeviceId = auth.DeviceId,
-                    DeviceName = auth.Device,
-                    Password = request.Pw,
-                    PasswordSha1 = request.Password,
-                    RemoteEndPoint = Request.RemoteIp,
-                    Username = request.Username
-                }).ConfigureAwait(false);
-
-                return ToOptimizedResult(result);
-            }
-            catch (SecurityException e)
-            {
-                // rethrow adding IP address to message
-                throw new SecurityException($"[{Request.RemoteIp}] {e.Message}", e);
-            }
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public Task Post(UpdateUserPassword request)
-        {
-            return PostAsync(request);
-        }
-
-        public async Task PostAsync(UpdateUserPassword request)
-        {
-            AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
-            var user = _userManager.GetUserById(request.Id);
-
-            if (user == null)
-            {
-                throw new ResourceNotFoundException("User not found");
-            }
-
-            if (request.ResetPassword)
-            {
-                await _userManager.ResetPassword(user).ConfigureAwait(false);
-            }
-            else
-            {
-                var success = await _userManager.AuthenticateUser(
-                    user.Username,
-                    request.CurrentPw,
-                    request.CurrentPassword,
-                    Request.RemoteIp,
-                    false).ConfigureAwait(false);
-
-                if (success == null)
-                {
-                    throw new ArgumentException("Invalid user or password entered.");
-                }
-
-                await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false);
-
-                var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
-
-                _sessionMananger.RevokeUserTokens(user.Id, currentToken);
-            }
-        }
-
-        public void Post(UpdateUserEasyPassword request)
-        {
-            AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
-            var user = _userManager.GetUserById(request.Id);
-
-            if (user == null)
-            {
-                throw new ResourceNotFoundException("User not found");
-            }
-
-            if (request.ResetPassword)
-            {
-                _userManager.ResetEasyPassword(user);
-            }
-            else
-            {
-                _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword);
-            }
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        public async Task Post(UpdateUser request)
-        {
-            var id = Guid.Parse(GetPathValue(1));
-
-            AssertCanUpdateUser(_authContext, _userManager, id, false);
-
-            var dtoUser = request;
-
-            var user = _userManager.GetUserById(id);
-
-            if (string.Equals(user.Username, dtoUser.Name, StringComparison.Ordinal))
-            {
-                await _userManager.UpdateUserAsync(user);
-                _userManager.UpdateConfiguration(user.Id, dtoUser.Configuration);
-            }
-            else
-            {
-                await _userManager.RenameUser(user, dtoUser.Name).ConfigureAwait(false);
-
-                _userManager.UpdateConfiguration(dtoUser.Id, dtoUser.Configuration);
-            }
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public async Task<object> Post(CreateUserByName request)
-        {
-            var newUser = _userManager.CreateUser(request.Name);
-
-            // no need to authenticate password for new user
-            if (request.Password != null)
-            {
-                await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
-            }
-
-            var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
-
-            return ToOptimizedResult(result);
-        }
-
-        public async Task<object> Post(ForgotPassword request)
-        {
-            var isLocal = Request.IsLocal || _networkManager.IsInLocalNetwork(Request.RemoteIp);
-
-            var result = await _userManager.StartForgotPasswordProcess(request.EnteredUsername, isLocal).ConfigureAwait(false);
-
-            return result;
-        }
-
-        public async Task<object> Post(ForgotPasswordPin request)
-        {
-            var result = await _userManager.RedeemPasswordResetPin(request.Pin).ConfigureAwait(false);
-
-            return result;
-        }
-
-        public void Post(UpdateUserConfiguration request)
-        {
-            AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
-
-            _userManager.UpdateConfiguration(request.Id, request);
-        }
-
-        public void Post(UpdateUserPolicy request)
-        {
-            var user = _userManager.GetUserById(request.Id);
-
-            // If removing admin access
-            if (!request.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))
-            {
-                if (_userManager.Users.Count(i => i.HasPermission(PermissionKind.IsAdministrator)) == 1)
-                {
-                    throw new ArgumentException("There must be at least one user in the system with administrative access.");
-                }
-            }
-
-            // If disabling
-            if (request.IsDisabled && user.HasPermission(PermissionKind.IsAdministrator))
-            {
-                throw new ArgumentException("Administrators cannot be disabled.");
-            }
-
-            // If disabling
-            if (request.IsDisabled && !user.HasPermission(PermissionKind.IsDisabled))
-            {
-                if (_userManager.Users.Count(i => !i.HasPermission(PermissionKind.IsDisabled)) == 1)
-                {
-                    throw new ArgumentException("There must be at least one enabled user in the system.");
-                }
-
-                var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
-                _sessionMananger.RevokeUserTokens(user.Id, currentToken);
-            }
-
-            _userManager.UpdatePolicy(request.Id, request);
-        }
-    }
-}