From 5c66f9e4716961dc40e0444c7d261dfd2e5841d7 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 20 Jul 2020 14:43:54 -0600 Subject: [PATCH] changes from merge --- .../Auth/DownloadPolicy/DownloadHandler.cs | 1 - .../Controllers/ActivityLogController.cs | 10 +- .../Controllers/DashboardController.cs | 1 - Jellyfin.Api/Controllers/FilterController.cs | 1 - .../Controllers/ItemRefreshController.cs | 1 - Jellyfin.Api/Controllers/LibraryController.cs | 1 - .../Controllers/LibraryStructureController.cs | 1 - Jellyfin.Api/Controllers/MoviesController.cs | 1 - .../Controllers/NotificationsController.cs | 1 - Jellyfin.Api/Controllers/PackageController.cs | 38 +- Jellyfin.Api/Controllers/PluginsController.cs | 1 - Jellyfin.Api/Controllers/TvShowsController.cs | 1 - Jellyfin.Api/Controllers/UserController.cs | 9 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 1 - .../Models/PlaybackDtos/TranscodingJobDto.cs | 3 - MediaBrowser.Api/ChannelService.cs | 340 ----- MediaBrowser.Api/ConfigurationService.cs | 144 -- MediaBrowser.Api/Devices/DeviceService.cs | 103 -- MediaBrowser.Api/DisplayPreferencesService.cs | 101 -- MediaBrowser.Api/EnvironmentService.cs | 285 ---- MediaBrowser.Api/FilterService.cs | 248 ---- MediaBrowser.Api/Images/ImageByNameService.cs | 277 ---- MediaBrowser.Api/Images/RemoteImageService.cs | 296 ---- MediaBrowser.Api/ItemLookupService.cs | 336 ----- MediaBrowser.Api/Library/LibraryService.cs | 1124 -------------- .../Library/LibraryStructureService.cs | 412 ------ MediaBrowser.Api/LiveTv/LiveTvService.cs | 1287 ----------------- MediaBrowser.Api/LocalizationService.cs | 111 -- MediaBrowser.Api/Movies/CollectionService.cs | 104 -- MediaBrowser.Api/Movies/MoviesService.cs | 414 ------ MediaBrowser.Api/Movies/TrailersService.cs | 88 -- MediaBrowser.Api/Music/AlbumsService.cs | 132 -- MediaBrowser.Api/Music/InstantMixService.cs | 196 --- MediaBrowser.Api/PackageService.cs | 197 --- MediaBrowser.Api/PlaylistService.cs | 216 --- MediaBrowser.Api/PluginService.cs | 277 ---- .../ScheduledTasks/ScheduledTaskService.cs | 234 --- MediaBrowser.Api/SearchService.cs | 332 ----- MediaBrowser.Api/Sessions/SessionService.cs | 499 ------- MediaBrowser.Api/Subtitles/SubtitleService.cs | 302 ---- MediaBrowser.Api/SuggestionsService.cs | 103 -- MediaBrowser.Api/System/ActivityLogService.cs | 69 - MediaBrowser.Api/System/SystemService.cs | 221 --- MediaBrowser.Api/TvShowsService.cs | 497 ------- .../UserLibrary/ArtistsService.cs | 143 -- .../UserLibrary/BaseItemsByNameService.cs | 388 ----- .../UserLibrary/BaseItemsRequest.cs | 478 ------ MediaBrowser.Api/UserLibrary/GenresService.cs | 140 -- MediaBrowser.Api/UserLibrary/ItemsService.cs | 514 ------- .../UserLibrary/PersonsService.cs | 146 -- .../UserLibrary/PlaystateService.cs | 456 ------ .../UserLibrary/StudiosService.cs | 132 -- .../UserLibrary/UserLibraryService.cs | 575 -------- .../UserLibrary/UserViewsService.cs | 148 -- MediaBrowser.Api/UserLibrary/YearsService.cs | 131 -- MediaBrowser.Api/UserService.cs | 598 -------- 56 files changed, 43 insertions(+), 12822 deletions(-) delete mode 100644 MediaBrowser.Api/ChannelService.cs delete mode 100644 MediaBrowser.Api/ConfigurationService.cs delete mode 100644 MediaBrowser.Api/Devices/DeviceService.cs delete mode 100644 MediaBrowser.Api/DisplayPreferencesService.cs delete mode 100644 MediaBrowser.Api/EnvironmentService.cs delete mode 100644 MediaBrowser.Api/FilterService.cs delete mode 100644 MediaBrowser.Api/Images/ImageByNameService.cs delete mode 100644 MediaBrowser.Api/Images/RemoteImageService.cs delete mode 100644 MediaBrowser.Api/ItemLookupService.cs delete mode 100644 MediaBrowser.Api/Library/LibraryService.cs delete mode 100644 MediaBrowser.Api/Library/LibraryStructureService.cs delete mode 100644 MediaBrowser.Api/LiveTv/LiveTvService.cs delete mode 100644 MediaBrowser.Api/LocalizationService.cs delete mode 100644 MediaBrowser.Api/Movies/CollectionService.cs delete mode 100644 MediaBrowser.Api/Movies/MoviesService.cs delete mode 100644 MediaBrowser.Api/Movies/TrailersService.cs delete mode 100644 MediaBrowser.Api/Music/AlbumsService.cs delete mode 100644 MediaBrowser.Api/Music/InstantMixService.cs delete mode 100644 MediaBrowser.Api/PackageService.cs delete mode 100644 MediaBrowser.Api/PlaylistService.cs delete mode 100644 MediaBrowser.Api/PluginService.cs delete mode 100644 MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs delete mode 100644 MediaBrowser.Api/SearchService.cs delete mode 100644 MediaBrowser.Api/Sessions/SessionService.cs delete mode 100644 MediaBrowser.Api/Subtitles/SubtitleService.cs delete mode 100644 MediaBrowser.Api/SuggestionsService.cs delete mode 100644 MediaBrowser.Api/System/ActivityLogService.cs delete mode 100644 MediaBrowser.Api/System/SystemService.cs delete mode 100644 MediaBrowser.Api/TvShowsService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/ArtistsService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs delete mode 100644 MediaBrowser.Api/UserLibrary/GenresService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/ItemsService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/PersonsService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/PlaystateService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/StudiosService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/UserLibraryService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/UserViewsService.cs delete mode 100644 MediaBrowser.Api/UserLibrary/YearsService.cs delete mode 100644 MediaBrowser.Api/UserService.cs diff --git a/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs b/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs index fcfa55dfec..b61680ab1a 100644 --- a/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/ActivityLogController.cs b/Jellyfin.Api/Controllers/ActivityLogController.cs index c287d1a773..12ea249731 100644 --- a/Jellyfin.Api/Controllers/ActivityLogController.cs +++ b/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 /// Optional. The record index to start at. All items with a lower index will be dropped from the results. /// Optional. The maximum number of records to return. /// Optional. The minimum date. Format = ISO. + /// Optional. Filter log entries if it has user id, or not. /// Activity log returned. /// A containing the log entries. [HttpGet("Entries")] @@ -42,10 +42,14 @@ namespace Jellyfin.Api.Controllers public ActionResult> GetLogEntries( [FromQuery] int? startIndex, [FromQuery] int? limit, - [FromQuery] DateTime? minDate) + [FromQuery] DateTime? minDate, + [FromQuery] bool? hasUserId) { var filterFunc = new Func, IQueryable>( - 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); } diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index 699ef6bf7b..e033c50d5c 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 288d4c5459..9ba5e11618 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 3801ce5b75..4697d869dc 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 2466b2ac89..5ad466c557 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index 881d3f1923..d3537a7a70 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index 144a7b554f..a9af1a2c33 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/NotificationsController.cs b/Jellyfin.Api/Controllers/NotificationsController.cs index 02aa39b248..1bb39b5f76 100644 --- a/Jellyfin.Api/Controllers/NotificationsController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 68ae05658e..a6c552790e 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/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; /// /// Initializes a new instance of the class. /// - /// Instance of Installation Manager. - public PackageController(IInstallationManager installationManager) + /// Instance of the interface. + /// Instance of the interface. + public PackageController(IInstallationManager installationManager, IServerConfigurationManager serverConfigurationManager) { _installationManager = installationManager; + _serverConfigurationManager = serverConfigurationManager; } /// @@ -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(); } + + /// + /// Gets all package repositories. + /// + /// Package repositories returned. + /// An containing the list of package repositories. + [HttpGet("/Repositories")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult> GetRepositories() + { + return _serverConfigurationManager.Configuration.PluginRepositories; + } + + /// + /// Sets the enabled and existing package repositories. + /// + /// The list of package repositories. + /// Package repositories saved. + /// A . + [HttpOptions("/Repositories")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult SetRepositories([FromBody] List repositoryInfos) + { + _serverConfigurationManager.Configuration.PluginRepositories = repositoryInfos; + return NoContent(); + } } } diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 056395a51d..48bb867aca 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index e5b0436214..d54bc10c03 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/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; diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 24194dcc23..8038ca0445 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/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(); } diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 44f662e6e0..34b371d3f8 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/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; diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs index dcc3224704..b9507a4e50 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs +++ b/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; diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs deleted file mode 100644 index 8c336b1c9d..0000000000 --- a/MediaBrowser.Api/ChannelService.cs +++ /dev/null @@ -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> - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Gets or sets a value indicating whether this instance is favorite. - /// - /// null if [is favorite] contains no value, true if [is favorite]; otherwise, false. - public bool? IsFavorite { get; set; } - } - - [Route("/Channels/{Id}/Features", "GET", Summary = "Gets features for a channel")] - public class GetChannelFeatures : IReturn - { - [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 - { - } - - [Route("/Channels/{Id}/Items", "GET", Summary = "Gets channel items")] - public class GetChannelItems : IReturn>, 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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Gets the filters. - /// - /// IEnumerable{ItemFilter}. - public IEnumerable GetFilters() - { - var val = Filters; - - return string.IsNullOrEmpty(val) - ? Array.Empty() - : val.Split(',').Select(v => Enum.Parse(v, true)); - } - - /// - /// Gets the order by. - /// - /// IEnumerable{ItemSortBy}. - public ValueTuple[] GetOrderBy() - { - return BaseItemsRequest.GetOrderBy(SortBy, SortOrder); - } - } - - [Route("/Channels/Items/Latest", "GET", Summary = "Gets channel items")] - public class GetLatestChannelItems : IReturn>, IHasItemFields - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Gets the filters. - /// - /// IEnumerable{ItemFilter}. - public IEnumerable GetFilters() - { - return string.IsNullOrEmpty(Filters) - ? Array.Empty() - : Filters.Split(',').Select(v => Enum.Parse(v, true)); - } - } - - [Authenticated] - public class ChannelService : BaseApiService - { - private readonly IChannelManager _channelManager; - private IUserManager _userManager; - - public ChannelService( - ILogger 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 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 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); - } - } -} diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs deleted file mode 100644 index 19369cccae..0000000000 --- a/MediaBrowser.Api/ConfigurationService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetConfiguration. - /// - [Route("/System/Configuration", "GET", Summary = "Gets application configuration")] - [Authenticated] - public class GetConfiguration : IReturn - { - } - - [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; } - } - - /// - /// Class UpdateConfiguration. - /// - [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 - { - } - - [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 - { - /// - /// The _json serializer. - /// - private readonly IJsonSerializer _jsonSerializer; - - /// - /// The _configuration manager. - /// - private readonly IServerConfigurationManager _configurationManager; - - private readonly IMediaEncoder _mediaEncoder; - - public ConfigurationService( - ILogger 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetConfiguration request) - { - return ToOptimizedResult(_configurationManager.Configuration); - } - - public object Get(GetNamedConfiguration request) - { - var result = _configurationManager.GetConfiguration(request.Key); - - return ToOptimizedResult(result); - } - - /// - /// Posts the specified configuraiton. - /// - /// The request. - 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(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()); - } - } -} diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs deleted file mode 100644 index 18860983ec..0000000000 --- a/MediaBrowser.Api/Devices/DeviceService.cs +++ /dev/null @@ -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> - { - } - - [Route("/Devices/Info", "GET", Summary = "Gets info for a device")] - [Authenticated(Roles = "Admin")] - public class GetDeviceInfo : IReturn - { - [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 - { - [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 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); - } - } - } -} diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs deleted file mode 100644 index c3ed40ad3c..0000000000 --- a/MediaBrowser.Api/DisplayPreferencesService.cs +++ /dev/null @@ -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 -{ - /// - /// Class UpdateDisplayPreferences. - /// - [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")] - public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - } - - /// - /// Class DisplayPreferencesService. - /// - [Authenticated] - public class DisplayPreferencesService : BaseApiService - { - /// - /// The _display preferences manager. - /// - private readonly IDisplayPreferencesRepository _displayPreferencesManager; - /// - /// The _json serializer. - /// - private readonly IJsonSerializer _jsonSerializer; - - /// - /// Initializes a new instance of the class. - /// - /// The json serializer. - /// The display preferences manager. - public DisplayPreferencesService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IJsonSerializer jsonSerializer, - IDisplayPreferencesRepository displayPreferencesManager) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _jsonSerializer = jsonSerializer; - _displayPreferencesManager = displayPreferencesManager; - } - - /// - /// Gets the specified request. - /// - /// The request. - public object Get(GetDisplayPreferences request) - { - var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client); - - return ToOptimizedResult(result); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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(_jsonSerializer.SerializeToString(request)); - - _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None); - } - } -} diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs deleted file mode 100644 index 720a710258..0000000000 --- a/MediaBrowser.Api/EnvironmentService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetDirectoryContents. - /// - [Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")] - public class GetDirectoryContents : IReturn> - { - /// - /// Gets or sets the path. - /// - /// The path. - [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Path { get; set; } - - /// - /// Gets or sets a value indicating whether [include files]. - /// - /// true if [include files]; otherwise, false. - [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; } - - /// - /// Gets or sets a value indicating whether [include directories]. - /// - /// true if [include directories]; otherwise, false. - [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 - { - /// - /// Gets or sets the path. - /// - /// The path. - [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> - { - /// - /// Gets or sets the path. - /// - /// The path. - [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Path { get; set; } - } - - /// - /// Class GetDrives. - /// - [Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")] - public class GetDrives : IReturn> - { - } - - /// - /// Class GetNetworkComputers. - /// - [Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")] - public class GetNetworkDevices : IReturn> - { - } - - [Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")] - public class GetParentPath : IReturn - { - /// - /// Gets or sets the path. - /// - /// The path. - [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 - { - } - - /// - /// Class EnvironmentService. - /// - [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)] - public class EnvironmentService : BaseApiService - { - private const char UncSeparator = '\\'; - private const string UncSeparatorString = "\\"; - - /// - /// The _network manager. - /// - private readonly INetworkManager _networkManager; - private readonly IFileSystem _fileSystem; - - /// - /// Initializes a new instance of the class. - /// - /// The network manager. - public EnvironmentService( - ILogger 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 }); - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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()); - } - - return ToOptimizedResult(GetFileSystemEntries(request).ToList()); - } - - [Obsolete] - public object Get(GetNetworkShares request) - => ToOptimizedResult(Array.Empty()); - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetDrives request) - { - var result = GetDrives().ToList(); - - return ToOptimizedResult(result); - } - - /// - /// Gets the list that is returned when an empty path is supplied. - /// - /// IEnumerable{FileSystemEntryInfo}. - private IEnumerable GetDrives() - { - return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Directory)); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetNetworkDevices request) - => ToOptimizedResult(Array.Empty()); - - /// - /// Gets the file system entries. - /// - /// The request. - /// IEnumerable{FileSystemEntryInfo}. - private IEnumerable 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; - } - } -} diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs deleted file mode 100644 index dcfdcbfed3..0000000000 --- a/MediaBrowser.Api/FilterService.cs +++ /dev/null @@ -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 - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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 - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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 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(), - 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() : 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 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; - } - } -} diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs deleted file mode 100644 index 2d405ac3d8..0000000000 --- a/MediaBrowser.Api/Images/ImageByNameService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetGeneralImage. - /// - [Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")] - public class GetGeneralImage - { - /// - /// Gets or sets the name. - /// - /// The name. - [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; } - } - - /// - /// Class GetRatingImage. - /// - [Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")] - public class GetRatingImage - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the theme. - /// - /// The theme. - [ApiMember(Name = "Theme", Description = "The theme to get the image from", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Theme { get; set; } - } - - /// - /// Class GetMediaInfoImage. - /// - [Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")] - public class GetMediaInfoImage - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the theme. - /// - /// The theme. - [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> - { - } - - [Route("/Images/Ratings", "GET", Summary = "Gets all rating images by name")] - [Authenticated] - public class GetRatingImages : IReturn> - { - } - - [Route("/Images/General", "GET", Summary = "Gets all general images by name")] - [Authenticated] - public class GetGeneralImages : IReturn> - { - } - - /// - /// Class ImageByNameService. - /// - public class ImageByNameService : BaseApiService - { - /// - /// The _app paths. - /// - private readonly IServerApplicationPaths _appPaths; - - private readonly IFileSystem _fileSystem; - - /// - /// Initializes a new instance of the class. - /// - public ImageByNameService( - ILogger 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 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(); - } - } - - 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; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public Task 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public Task 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); - } - } -} diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs deleted file mode 100644 index 86464b4b9a..0000000000 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ /dev/null @@ -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 - { - [ApiMember(Name = "Type", Description = "The image type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public ImageType? Type { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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> - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 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 GetImageProviders(BaseItem item) - { - return _providerManager.GetRemoteImageProviderInfo(item).ToList(); - } - - public async Task 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; - } - - /// - /// Posts the specified request. - /// - /// The request. - public Task Post(DownloadRemoteImage request) - { - var item = _libraryManager.GetItemById(request.Id); - - return DownloadRemoteImage(item, request); - } - - /// - /// Downloads the remote image. - /// - /// The item. - /// The request. - /// Task. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public async Task 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); - } - - /// - /// Downloads the image. - /// - /// The URL. - /// The URL hash. - /// The pointer cache path. - /// Task. - 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); - } - - /// - /// Gets the full cache path. - /// - /// The filename. - /// System.String. - private string GetFullCachePath(string filename) - { - return Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); - } - } -} diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs deleted file mode 100644 index 8624112099..0000000000 --- a/MediaBrowser.Api/ItemLookupService.cs +++ /dev/null @@ -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> - { - /// - /// Gets or sets the id. - /// - /// The id. - [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, IReturn> - { - } - - [Route("/Items/RemoteSearch/Trailer", "POST")] - [Authenticated] - public class GetTrailerRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/MusicVideo", "POST")] - [Authenticated] - public class GetMusicVideoRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/Series", "POST")] - [Authenticated] - public class GetSeriesRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/BoxSet", "POST")] - [Authenticated] - public class GetBoxSetRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/MusicArtist", "POST")] - [Authenticated] - public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/MusicAlbum", "POST")] - [Authenticated] - public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/Person", "POST")] - [Authenticated(Roles = "Admin")] - public class GetPersonRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [Route("/Items/RemoteSearch/Book", "POST")] - [Authenticated] - public class GetBookRemoteSearchResults : RemoteSearchQuery, IReturn> - { - } - - [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 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 Post(GetTrailerRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetBookRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetMovieRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetSeriesRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetBoxSetRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetMusicVideoRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetPersonRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetMusicAlbumRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Post(GetMusicArtistRemoteSearchResults request) - { - var result = await _providerManager.GetRemoteSearchResults(request, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public Task 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); - } - - /// - /// Gets the remote image. - /// - /// The request. - /// Task{System.Object}. - private async Task 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); - } - - /// - /// Downloads the image. - /// - /// Name of the provider. - /// The URL. - /// The URL hash. - /// The pointer cache path. - /// Task. - 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); - } - - /// - /// Gets the full cache path. - /// - /// The filename. - /// System.String. - private string GetFullCachePath(string filename) - => Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); - } -} diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs deleted file mode 100644 index 6555864dc5..0000000000 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ /dev/null @@ -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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class GetCriticReviews. - /// - [Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")] - [Authenticated] - public class GetCriticReviews : IReturn> - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - } - - /// - /// Class GetThemeSongs. - /// - [Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")] - [Authenticated] - public class GetThemeSongs : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - } - - /// - /// Class GetThemeVideos. - /// - [Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")] - [Authenticated] - public class GetThemeVideos : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - } - - /// - /// Class GetThemeVideos. - /// - [Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")] - [Authenticated] - public class GetThemeMedia : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - [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 - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class GetPhyscialPaths. - /// - [Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")] - [Authenticated(Roles = "Admin")] - public class GetPhyscialPaths : IReturn> - { - } - - [Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")] - [Authenticated] - public class GetMediaFolders : IReturn> - { - [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 Updates { get; set; } - } - - [Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")] - [Authenticated(Roles = "download")] - public class GetDownload - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - 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; } - } - - /// - /// Class LibraryService. - /// - 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 _moviesServiceLogger; - - /// - /// Initializes a new instance of the class. - /// - public LibraryService( - ILogger logger, - ILogger 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(); - - 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()) - .Distinct() - .ToArray(), - - DefaultImageOptions = defaultImageOptions ?? Array.Empty() - }); - } - - 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(); - } - - return GetSimilarItemsResult(request, new[] { item.GetType().Name }); - } - - private QueryResult 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 itemsResult; - - if (item is MusicArtist) - { - query.IncludeItemTypes = Array.Empty(); - - 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 - { - 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 - { - 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(); - } - - foreach (var item in movies) - { - _libraryMonitor.ReportFileSystemChanged(item.Path); - } - } - - public Task 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(); - - 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 Get(GetFile request) - { - var item = _libraryManager.GetItemById(request.Id); - - return ResultFactory.GetStaticFileResult(Request, item.Path); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetPhyscialPaths request) - { - var result = _libraryManager.RootFolder.Children - .SelectMany(c => c.PhysicalLocations) - .ToList(); - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetAncestors request) - { - var result = GetAncestors(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the ancestors. - /// - /// The request. - /// Task{BaseItemDto[]}. - public List GetAncestors(GetAncestors request) - { - var item = _libraryManager.GetItemById(request.Id); - - var baseItemDtos = new List(); - - 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; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetCriticReviews request) - { - return new QueryResult(); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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; - } - - /// - /// Posts the specified request. - /// - /// The request. - public async Task Post(RefreshLibrary request) - { - try - { - await _libraryManager.ValidateMediaLibrary(new SimpleProgress(), CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error refreshing library"); - } - } - - /// - /// Deletes the specified request. - /// - /// The request. - public void Delete(DeleteItems request) - { - var ids = string.IsNullOrWhiteSpace(request.Ids) - ? Array.Empty() - : 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); - } - } - - /// - /// Deletes the specified request. - /// - /// The request. - 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() - }); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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 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 - }; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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 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 - }; - } - } -} diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs deleted file mode 100644 index b69550ed1a..0000000000 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetDefaultVirtualFolders. - /// - [Route("/Library/VirtualFolders", "GET")] - public class GetVirtualFolders : IReturn> - { - /// - /// Gets or sets the user id. - /// - /// The user id. - public string UserId { get; set; } - } - - [Route("/Library/VirtualFolders", "POST")] - public class AddVirtualFolder : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the type of the collection. - /// - /// The type of the collection. - public string CollectionType { get; set; } - - /// - /// Gets or sets a value indicating whether [refresh library]. - /// - /// true if [refresh library]; otherwise, false. - public bool RefreshLibrary { get; set; } - - /// - /// Gets or sets the path. - /// - /// The path. - public string[] Paths { get; set; } - - public LibraryOptions LibraryOptions { get; set; } - } - - [Route("/Library/VirtualFolders", "DELETE")] - public class RemoveVirtualFolder : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets a value indicating whether [refresh library]. - /// - /// true if [refresh library]; otherwise, false. - public bool RefreshLibrary { get; set; } - } - - [Route("/Library/VirtualFolders/Name", "POST")] - public class RenameVirtualFolder : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string NewName { get; set; } - - /// - /// Gets or sets a value indicating whether [refresh library]. - /// - /// true if [refresh library]; otherwise, false. - public bool RefreshLibrary { get; set; } - } - - [Route("/Library/VirtualFolders/Paths", "POST")] - public class AddMediaPath : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Path { get; set; } - - public MediaPathInfo PathInfo { get; set; } - - /// - /// Gets or sets a value indicating whether [refresh library]. - /// - /// true if [refresh library]; otherwise, false. - public bool RefreshLibrary { get; set; } - } - - [Route("/Library/VirtualFolders/Paths/Update", "POST")] - public class UpdateMediaPath : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - public MediaPathInfo PathInfo { get; set; } - } - - [Route("/Library/VirtualFolders/Paths", "DELETE")] - public class RemoveMediaPath : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Path { get; set; } - - /// - /// Gets or sets a value indicating whether [refresh library]. - /// - /// true if [refresh library]; otherwise, false. - public bool RefreshLibrary { get; set; } - } - - [Route("/Library/VirtualFolders/LibraryOptions", "POST")] - public class UpdateLibraryOptions : IReturnVoid - { - public string Id { get; set; } - - public LibraryOptions LibraryOptions { get; set; } - } - - /// - /// Class LibraryStructureService. - /// - [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)] - public class LibraryStructureService : BaseApiService - { - /// - /// The _app paths. - /// - private readonly IServerApplicationPaths _appPaths; - - /// - /// The _library manager. - /// - private readonly ILibraryManager _libraryManager; - private readonly ILibraryMonitor _libraryMonitor; - - - /// - /// Initializes a new instance of the class. - /// - public LibraryStructureService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - ILibraryManager libraryManager, - ILibraryMonitor libraryMonitor) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _appPaths = serverConfigurationManager.ApplicationPaths; - _libraryManager = libraryManager; - _libraryMonitor = libraryMonitor; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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(), 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(); - } - }); - } - } - - /// - /// Deletes the specified request. - /// - /// The request. - public Task Delete(RemoveVirtualFolder request) - { - return _libraryManager.RemoveVirtualFolder(request.Name, request.RefreshLibrary); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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(), 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(); - } - }); - } - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(UpdateMediaPath request) - { - if (string.IsNullOrWhiteSpace(request.Name)) - { - throw new ArgumentNullException(nameof(request)); - } - - _libraryManager.UpdateMediaPath(request.Name, request.PathInfo); - } - - /// - /// Deletes the specified request. - /// - /// The request. - 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(), 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(); - } - }); - } - } - } -} diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs deleted file mode 100644 index 830372dd8e..0000000000 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ /dev/null @@ -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 -{ - /// - /// This is insecure right now to avoid windows phone refactoring. - /// - [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")] - [Authenticated] - public class GetLiveTvInfo : IReturn - { - } - - [Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")] - [Authenticated] - public class GetChannels : IReturn>, 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; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - - /// - /// Gets the order by. - /// - /// IEnumerable{ItemSortBy}. - public string[] GetOrderBy() - { - var val = SortBy; - - if (string.IsNullOrEmpty(val)) - { - return Array.Empty(); - } - - return val.Split(','); - } - - public GetChannels() - { - AddCurrentProgram = true; - } - } - - [Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")] - [Authenticated] - public class GetChannel : IReturn - { - /// - /// Gets or sets the id. - /// - /// The id. - [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>, 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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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>, 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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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> - { - [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 - { - [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 - { - [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 - { - [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 - { - [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> - { - [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>, 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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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>, 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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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 - { - [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 - { - [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> - { - [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 - { - [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 - { - } - - [Route("/LiveTv/TunerHosts", "POST", Summary = "Adds a tuner host")] - [Authenticated] - public class AddTunerHost : TunerHostInfo, IReturn - { - } - - [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 - { - } - - [Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")] - [Authenticated] - public class AddListingProvider : ListingsProviderInfo, IReturn - { - 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> - { - [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 TunerChannels { get; set; } - - public List 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> - { - } - - [Route("/LiveTv/Tuners/Discvover", "GET")] - [Authenticated] - public class DiscoverTuners : IReturn> - { - 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 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 - { - 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(StringComparer.OrdinalIgnoreCase) - { - [HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType(path) - }; - - return new ProgressiveFileCopier(_streamHelper, path, outputHeaders, Logger) - { - AllowEndOfFile = false - }; - } - - public async Task Get(DiscoverTuners request) - { - var result = await _liveTvManager.DiscoverTuners(request.NewDevicesOnly, CancellationToken.None).ConfigureAwait(false); - return ToOptimizedResult(result); - } - - public async Task Get(GetLiveStreamFile request) - { - var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(request.Id, CancellationToken.None).ConfigureAwait(false); - - var directStreamProvider = liveStreamInfo; - - var outputHeaders = new Dictionary(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 Post(SetChannelMapping request) - { - return await _liveTvManager.SetChannelMapping(request.ProviderId, request.TunerChannelId, request.ProviderChannelId).ConfigureAwait(false); - } - - public async Task 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 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 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); - } - - /// - /// Gets the hashed string. - /// - 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 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("livetv"); - } - - private void UpdateConfiguration(LiveTvOptions options) - { - ServerConfigurationManager.SaveConfiguration("livetv", options); - } - - public async Task 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 - { - 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 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()); - } - - 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 Get(GetTimer request) - { - var result = await _liveTvManager.GetTimer(request.Id, CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task 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 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 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 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 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()); - } - - 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); - } - } -} diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs deleted file mode 100644 index d6b5f51950..0000000000 --- a/MediaBrowser.Api/LocalizationService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetCultures. - /// - [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")] - public class GetCultures : IReturn - { - } - - /// - /// Class GetCountries. - /// - [Route("/Localization/Countries", "GET", Summary = "Gets known countries")] - public class GetCountries : IReturn - { - } - - /// - /// Class ParentalRatings. - /// - [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")] - public class GetParentalRatings : IReturn - { - } - - /// - /// Class ParentalRatings. - /// - [Route("/Localization/Options", "GET", Summary = "Gets localization options")] - public class GetLocalizationOptions : IReturn - { - } - - /// - /// Class CulturesService. - /// - [Authenticated(AllowBeforeStartupWizard = true)] - public class LocalizationService : BaseApiService - { - /// - /// The _localization. - /// - private readonly ILocalizationManager _localization; - - /// - /// Initializes a new instance of the class. - /// - /// The localization. - public LocalizationService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - ILocalizationManager localization) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _localization = localization; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetParentalRatings request) - { - var result = _localization.GetParentalRatings(); - - return ToOptimizedResult(result); - } - - public object Get(GetLocalizationOptions request) - { - var result = _localization.GetLocalizationOptions(); - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetCountries request) - { - var result = _localization.GetCountries(); - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetCultures request) - { - var result = _localization.GetCultures(); - - return ToOptimizedResult(result); - } - } - -} diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs deleted file mode 100644 index e9629439de..0000000000 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ /dev/null @@ -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 - { - [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 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, ',')); - } - } -} diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs deleted file mode 100644 index 34cccffa38..0000000000 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ /dev/null @@ -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, 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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Specify this to localize the search to a specific item or folder. Omit to use the root. - /// - /// The parent id. - [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; } - } - - /// - /// Class MoviesService. - /// - [Authenticated] - public class MoviesService : BaseApiService - { - /// - /// The _user manager. - /// - private readonly IUserManager _userManager; - - private readonly ILibraryManager _libraryManager; - - private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; - - /// - /// Initializes a new instance of the class. - /// - public MoviesService( - ILogger 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 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 { 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 - { - Items = returnList, - - TotalRecordCount = itemsResult.Count - }; - - return result; - } - - private IEnumerable GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions) - { - var categories = new List(); - - 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(i, SortOrder.Descending)).ToArray(), - Limit = 7, - ParentId = parentIdGuid, - Recursive = true, - IsPlayed = true, - DtoOptions = dtoOptions - }; - - var recentlyPlayedMovies = _libraryManager.GetItemList(query); - - var itemTypes = new List { 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(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> - { - // 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 GetWithDirector( - User user, - IEnumerable names, - int itemLimit, - DtoOptions dtoOptions, - RecommendationType type) - { - var itemTypes = new List { 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 GetWithActor(User user, IEnumerable names, int itemLimit, DtoOptions dtoOptions, RecommendationType type) - { - var itemTypes = new List { 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 GetSimilarTo(User user, List baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type) - { - var itemTypes = new List { 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 GetActors(List 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 GetDirectors(List 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(); - } - } -} diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs deleted file mode 100644 index ca9f9d03b2..0000000000 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ /dev/null @@ -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> - { - } - - /// - /// Class TrailersService. - /// - [Authenticated] - public class TrailersService : BaseApiService - { - /// - /// The _user manager. - /// - private readonly IUserManager _userManager; - - /// - /// The _library manager. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// The logger for the created instances. - /// - private readonly ILogger _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(), serverConfigurationManager, httpResultFactory) - { - _userManager = userManager; - _libraryManager = libraryManager; - _dtoService = dtoService; - _localizationManager = localizationManager; - _json = json; - _authContext = authContext; - _logger = loggerFactory.CreateLogger(); - } - - public object Get(Getrailers request) - { - var json = _json.SerializeToString(request); - var getItems = _json.DeserializeFromString(json); - - getItems.IncludeItemTypes = "Trailer"; - - return new ItemsService( - _logger, - ServerConfigurationManager, - ResultFactory, - _userManager, - _libraryManager, - _localizationManager, - _dtoService, - _authContext) - { - Request = Request, - }.Get(getItems); - } - } -} diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs deleted file mode 100644 index 74d3cce12a..0000000000 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ /dev/null @@ -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 - { - /// - /// The _user manager. - /// - private readonly IUserManager _userManager; - - /// - /// The _user data repository. - /// - private readonly IUserDataManager _userDataRepository; - /// - /// The _library manager. - /// - private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; - private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; - - public AlbumsService( - ILogger 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the album similarity score. - /// - /// The item1. - /// The item1 people. - /// All people. - /// The item2. - /// System.Int32. - private int GetAlbumSimilarityScore(BaseItem item1, List item1People, List 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( - album2.GetAllArtists().DistinctNames(), - StringComparer.OrdinalIgnoreCase); - - return points + artists1.Where(artists2.Contains).Sum(i => 5); - } - } -} diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs deleted file mode 100644 index ebd3eb64a1..0000000000 --- a/MediaBrowser.Api/Music/InstantMixService.cs +++ /dev/null @@ -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 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 items, User user, BaseGetSimilarItems request, DtoOptions dtoOptions) - { - var list = items; - - var result = new QueryResult - { - 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; - } - } -} diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs deleted file mode 100644 index a84556fcc4..0000000000 --- a/MediaBrowser.Api/PackageService.cs +++ /dev/null @@ -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, IReturnVoid - { - } - - /// - /// Class GetPackage. - /// - [Route("/Packages/{Name}", "GET", Summary = "Gets a package, by name or assembly guid")] - [Authenticated] - public class GetPackage : IReturn - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The name of the package", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "AssemblyGuid", Description = "The guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string AssemblyGuid { get; set; } - } - - /// - /// Class GetPackages. - /// - [Route("/Packages", "GET", Summary = "Gets available packages")] - [Authenticated] - public class GetPackages : IReturn - { - } - - /// - /// Class InstallPackage. - /// - [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")] - [Authenticated(Roles = "Admin")] - public class InstallPackage : IReturnVoid - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "Package name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Name { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "AssemblyGuid", Description = "Guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string AssemblyGuid { get; set; } - - /// - /// Gets or sets the version. - /// - /// The version. - [ApiMember(Name = "Version", Description = "Optional version. Defaults to latest version.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Version { get; set; } - } - - /// - /// Class CancelPackageInstallation. - /// - [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")] - [Authenticated(Roles = "Admin")] - public class CancelPackageInstallation : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Installation Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string Id { get; set; } - } - - /// - /// Class PackageService. - /// - public class PackageService : BaseApiService - { - private readonly IInstallationManager _installationManager; - private readonly IServerConfigurationManager _serverConfigurationManager; - - public PackageService( - ILogger 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(); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public async Task Get(GetPackages request) - { - IEnumerable packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); - - return ToOptimizedResult(packages.ToArray()); - } - - /// - /// Posts the specified request. - /// - /// The request. - /// - 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); - } - - /// - /// Deletes the specified request. - /// - /// The request. - public void Delete(CancelPackageInstallation request) - { - _installationManager.CancelInstallation(new Guid(request.Id)); - } - } -} diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs deleted file mode 100644 index 5513c08922..0000000000 --- a/MediaBrowser.Api/PlaylistService.cs +++ /dev/null @@ -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 - { - [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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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>, IHasDtoOptions - { - [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid Id { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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 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 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 - { - Items = dtos, - TotalRecordCount = count - }; - - return ToOptimizedResult(result); - } - } -} diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs deleted file mode 100644 index 7d976ceaac..0000000000 --- a/MediaBrowser.Api/PluginService.cs +++ /dev/null @@ -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 -{ - /// - /// Class Plugins. - /// - [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")] - [Authenticated] - public class GetPlugins : IReturn - { - public bool? IsAppStoreEnabled { get; set; } - } - - /// - /// Class UninstallPlugin. - /// - [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")] - [Authenticated(Roles = "Admin")] - public class UninstallPlugin : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string Id { get; set; } - } - - /// - /// Class GetPluginConfiguration. - /// - [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")] - [Authenticated] - public class GetPluginConfiguration - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class UpdatePluginConfiguration. - /// - [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")] - [Authenticated] - public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// The raw Http Request Input Stream. - /// - /// The request stream. - 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 - { - [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - } - - /// - /// Class GetPluginSecurityInfo. - /// - [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information", IsHidden = true)] - [Authenticated] - public class GetPluginSecurityInfo : IReturn - { - } - - /// - /// Class UpdatePluginSecurityInfo. - /// - [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; } - } - /// - /// Class PluginsService. - /// - public class PluginService : BaseApiService - { - /// - /// The _json serializer. - /// - private readonly IJsonSerializer _jsonSerializer; - - /// - /// The _app host. - /// - private readonly IApplicationHost _appHost; - private readonly IInstallationManager _installationManager; - - public PluginService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IJsonSerializer jsonSerializer, - IApplicationHost appHost, - IInstallationManager installationManager) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _appHost = appHost; - _installationManager = installationManager; - _jsonSerializer = jsonSerializer; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetRegistrationStatus request) - { - var record = new MBRegistrationRecord - { - IsRegistered = true, - RegChecked = true, - TrialVersion = false, - IsValid = true, - RegError = false - }; - - return ToOptimizedResult(record); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetPlugins request) - { - var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray(); - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetPluginSecurityInfo request) - { - var result = new PluginSecurityInfo - { - IsMBSupporter = true, - SupporterKey = "IAmTotallyLegit" - }; - - return ToOptimizedResult(result); - } - - /// - /// Posts the specified request. - /// - /// The request. - public Task Post(UpdatePluginSecurityInfo request) - { - return Task.CompletedTask; - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Deletes the specified request. - /// - /// The request. - public void Delete(UninstallPlugin request) - { - var guid = new Guid(request.Id); - var plugin = _appHost.Plugins.First(p => p.Id == guid); - - _installationManager.UninstallPlugin(plugin); - } - } -} diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs deleted file mode 100644 index 86b00316ad..0000000000 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetScheduledTask. - /// - [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")] - public class GetScheduledTask : IReturn - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class GetScheduledTasks. - /// - [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")] - public class GetScheduledTasks : IReturn - { - [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; } - } - - /// - /// Class StartScheduledTask. - /// - [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")] - public class StartScheduledTask : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - } - - /// - /// Class StopScheduledTask. - /// - [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")] - public class StopScheduledTask : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string Id { get; set; } - } - - /// - /// Class UpdateScheduledTaskTriggers. - /// - [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")] - public class UpdateScheduledTaskTriggers : List, IReturnVoid - { - /// - /// Gets or sets the task id. - /// - /// The task id. - [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - } - - /// - /// Class ScheduledTasksService. - /// - [Authenticated(Roles = "Admin")] - public class ScheduledTaskService : BaseApiService - { - /// - /// The task manager. - /// - private readonly ITaskManager _taskManager; - - /// - /// Initializes a new instance of the class. - /// - /// The task manager. - /// taskManager - public ScheduledTaskService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - ITaskManager taskManager) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _taskManager = taskManager; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// IEnumerable{TaskInfo}. - public object Get(GetScheduledTasks request) - { - IEnumerable 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// IEnumerable{TaskInfo}. - /// Task not found - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - /// Task not found - 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()); - } - - /// - /// Posts the specified request. - /// - /// The request. - /// Task not found - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - /// Task not found - 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(); - } - } -} diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs deleted file mode 100644 index 64ee69300e..0000000000 --- a/MediaBrowser.Api/SearchService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetSearchHints. - /// - [Route("/Search/Hints", "GET", Summary = "Gets search hints based on a search term")] - public class GetSearchHints : IReturn - { - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Search characters used to find items. - /// - /// The index by. - [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; - } - } - - /// - /// Class SearchService. - /// - [Authenticated] - public class SearchService : BaseApiService - { - /// - /// The _search engine. - /// - private readonly ISearchEngine _searchEngine; - private readonly ILibraryManager _libraryManager; - private readonly IDtoService _dtoService; - private readonly IImageProcessor _imageProcessor; - - /// - /// Initializes a new instance of the class. - /// - /// The search engine. - /// The library manager. - /// The dto service. - /// The image processor. - public SearchService( - ILogger 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; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSearchHints request) - { - var result = GetSearchHintsAsync(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the search hints async. - /// - /// The request. - /// Task{IEnumerable{SearchHintResult}}. - 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() - }; - } - - /// - /// Gets the search hint result. - /// - /// The hint info. - /// SearchHintResult. - 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(item, ImageType.Thumb); - } - - if (itemWithImage == null) - { - itemWithImage = GetParentWithImage(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(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(BaseItem item, ImageType type) - where T : BaseItem - { - return item.GetParents().OfType().FirstOrDefault(i => i.HasImage(type)); - } - } -} diff --git a/MediaBrowser.Api/Sessions/SessionService.cs b/MediaBrowser.Api/Sessions/SessionService.cs deleted file mode 100644 index 50adc56980..0000000000 --- a/MediaBrowser.Api/Sessions/SessionService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetSessions. - /// - [Route("/Sessions", "GET", Summary = "Gets a list of sessions")] - [Authenticated] - public class GetSessions : IReturn - { - [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; } - } - - /// - /// Class DisplayContent. - /// - [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")] - [Authenticated] - public class DisplayContent : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Artist, Genre, Studio, Person, or any kind of BaseItem. - /// - /// The type of the item. - [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ItemType { get; set; } - - /// - /// Artist name, genre name, item Id, etc. - /// - /// The item identifier. - [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ItemId { get; set; } - - /// - /// Gets or sets the name of the item. - /// - /// The name of the item. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Gets or sets the command. - /// - /// The play command. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Gets or sets the command. - /// - /// The play command. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - } - - [Route("/Auth/PasswordResetProviders", "GET")] - [Authenticated(Roles = "Admin")] - public class GetPasswordResetProviders : IReturn - { - } - - /// - /// Class SessionsService. - /// - public class SessionService : BaseApiService - { - /// - /// The session manager. - /// - private readonly ISessionManager _sessionManager; - - private readonly IUserManager _userManager; - private readonly IAuthorizationContext _authContext; - private readonly IDeviceManager _deviceManager; - private readonly ISessionContext _sessionContext; - - public SessionService( - ILogger 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - } -} diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs deleted file mode 100644 index a70da8e56c..0000000000 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ /dev/null @@ -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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - /// - /// Gets or sets the id. - /// - /// The id. - [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 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 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()); - } - - public async Task 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 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 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 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"); - } - }); - } - } -} diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs deleted file mode 100644 index 17afa8e79c..0000000000 --- a/MediaBrowser.Api/SuggestionsService.cs +++ /dev/null @@ -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> - { - 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 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 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 - { - TotalRecordCount = result.TotalRecordCount, - Items = dtoList - }; - } - - private QueryResult GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions) - { - return _libraryManager.GetItemsResult(new InternalItemsQuery(user) - { - OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple(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 - }); - } - } -} diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs deleted file mode 100644 index 4afa6e114a..0000000000 --- a/MediaBrowser.Api/System/ActivityLogService.cs +++ /dev/null @@ -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> - { - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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 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>( - 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); - } - } -} diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs deleted file mode 100644 index e0e20d828e..0000000000 --- a/MediaBrowser.Api/System/SystemService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetSystemInfo. - /// - [Route("/System/Info", "GET", Summary = "Gets information about the server")] - [Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)] - public class GetSystemInfo : IReturn - { - } - - [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")] - public class GetPublicSystemInfo : IReturn - { - } - - [Route("/System/Ping", "POST")] - [Route("/System/Ping", "GET")] - public class PingSystem : IReturnVoid - { - } - - /// - /// Class RestartApplication. - /// - [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] - [Authenticated(Roles = "Admin", AllowLocal = true)] - public class RestartApplication - { - } - - /// - /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server. - /// - [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 - { - } - - [Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")] - [Authenticated] - public class GetEndpointInfo : IReturn - { - 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 - { - } - - /// - /// Class SystemInfoService. - /// - public class SystemService : BaseApiService - { - /// - /// The _app host. - /// - private readonly IServerApplicationHost _appHost; - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - private readonly INetworkManager _network; - - /// - /// Initializes a new instance of the class. - /// - /// The app host. - /// The file system. - /// jsonSerializer - public SystemService( - ILogger 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 files; - - try - { - files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false); - } - catch (IOException ex) - { - Logger.LogError(ex, "Error getting logs"); - files = Enumerable.Empty(); - } - - 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 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public async Task Get(GetSystemInfo request) - { - var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - public async Task Get(GetPublicSystemInfo request) - { - var result = await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(RestartApplication request) - { - _appHost.Restart(); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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) - }); - } - } -} diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs deleted file mode 100644 index 165abd613d..0000000000 --- a/MediaBrowser.Api/TvShowsService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetNextUpEpisodes. - /// - [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")] - public class GetNextUpEpisodes : IReturn>, IHasDtoOptions - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - - /// - /// Specify this to localize the search to a specific item or folder. Omit to use the root. - /// - /// The parent id. - [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>, IHasDtoOptions - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - - /// - /// Specify this to localize the search to a specific item or folder. Omit to use the root. - /// - /// The parent id. - [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>, IHasItemFields, IHasDtoOptions - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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>, IHasItemFields, IHasDtoOptions - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - } - - /// - /// Class TvShowsService. - /// - [Authenticated] - public class TvShowsService : BaseApiService - { - /// - /// The _user manager. - /// - private readonly IUserManager _userManager; - - /// - /// The _library manager. - /// - private readonly ILibraryManager _libraryManager; - - private readonly IDtoService _dtoService; - private readonly ITVSeriesManager _tvSeriesManager; - private readonly IAuthorizationContext _authContext; - - /// - /// Initializes a new instance of the class. - /// - /// The user manager. - /// The user data repository. - /// The library manager. - public TvShowsService( - ILogger 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(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 - { - TotalRecordCount = itemsResult.Count, - Items = returnItems - }; - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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 - { - TotalRecordCount = result.TotalRecordCount, - Items = returnItems - }); - } - - /// - /// Applies the paging. - /// - /// The items. - /// The start index. - /// The limit. - /// IEnumerable{BaseItem}. - private IEnumerable ApplyPaging(IEnumerable 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 - { - 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 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() : ((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 - { - TotalRecordCount = episodes.Count, - Items = dtos - }; - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs deleted file mode 100644 index 9875e02084..0000000000 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetArtists. - /// - [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 - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - } - - /// - /// Class ArtistsService. - /// - [Authenticated] - public class ArtistsService : BaseItemsByNameService - { - public ArtistsService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IUserDataManager userDataRepository, - IDtoService dtoService, - IAuthorizationContext authorizationContext) - : base( - logger, - serverConfigurationManager, - httpResultFactory, - userManager, - libraryManager, - userDataRepository, - dtoService, - authorizationContext) - { - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetArtist request) - { - return GetItem(request); - } - - /// - /// Gets the item. - /// - /// The request. - /// Task{BaseItemDto}. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetArtists request) - { - return GetResultSlim(request); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Tuple{System.StringFunc{System.Int32}}}. - protected override IEnumerable GetAllItems(GetItemsByName request, IList items) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs deleted file mode 100644 index fd639caf11..0000000000 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ /dev/null @@ -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 -{ - /// - /// Class BaseItemsByNameService. - /// - /// The type of the T item type. - public abstract class BaseItemsByNameService : BaseApiService - where TItemType : BaseItem, IItemByName - { - /// - /// Initializes a new instance of the class. - /// - /// The user manager. - /// The library manager. - /// The user data repository. - /// The dto service. - protected BaseItemsByNameService( - ILogger> 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; - } - - /// - /// Gets the _user manager. - /// - protected IUserManager UserManager { get; } - - /// - /// Gets the library manager. - /// - 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 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 - { - 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; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// Task{ItemsResult}. - protected QueryResult 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 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 ibnItems = ibnItemsArray; - - var result = new QueryResult - { - 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>(i, new List())); - - var dtos = tuples.Select(i => DtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user)); - - result.Items = dtos.Where(i => i != null).ToArray(); - - return result; - } - - /// - /// Filters the items. - /// - /// The request. - /// The f. - /// The exclude item types. - /// The include item types. - /// The media types. - /// IEnumerable{BaseItem}. - 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; - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Task{`0}}. - protected abstract IEnumerable GetAllItems(GetItemsByName request, IList items); - } - - /// - /// Class GetItemsByName. - /// - public class GetItemsByName : BaseItemsRequest, IReturn> - { - public GetItemsByName() - { - Recursive = true; - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs deleted file mode 100644 index 344861a496..0000000000 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ /dev/null @@ -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; - } - - /// - /// Gets or sets the max offical rating. - /// - /// The max offical rating. - [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; } - - /// - /// Skips over a given number of items within the results. Use for paging. - /// - /// The start index. - [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; } - - /// - /// The maximum number of items to return. - /// - /// The limit. - [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; } - - /// - /// Whether or not to perform the query recursively. - /// - /// true if recursive; otherwise, false. - [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; } - - /// - /// Gets or sets the sort order. - /// - /// The sort order. - [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string SortOrder { get; set; } - - /// - /// Specify this to localize the search to a specific item or folder. Omit to use the root. - /// - /// The parent id. - [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; } - - /// - /// Fields to return within the items, in addition to basic information. - /// - /// The fields. - [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; } - - /// - /// Gets or sets the exclude item types. - /// - /// The exclude item types. - [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; } - - /// - /// Gets or sets the include item types. - /// - /// The include item types. - [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; } - - /// - /// Filters to apply to the results. - /// - /// The filters. - [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; } - - /// - /// Gets or sets the Isfavorite option. - /// - /// IsFavorite - [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; } - - /// - /// Gets or sets the media types. - /// - /// The media types. - [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; } - - /// - /// Gets or sets the image types. - /// - /// The image types. - [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; } - - /// - /// What to sort the results by. - /// - /// The sort by. - [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; } - - /// - /// Limit results to items containing specific genres. - /// - /// The genres. - [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; } - - /// - /// Limit results to items containing specific years. - /// - /// The years. - [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; } - - /// - /// Limit results to items containing a specific person. - /// - /// The person. - [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; } - - /// - /// If the Person filter is used, this can also be used to restrict to a specific person type. - /// - /// The type of the person. - [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; } - - /// - /// Limit results to items containing specific studios. - /// - /// The studios. - [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; } - - /// - /// Gets or sets the studios. - /// - /// The studios. - [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; } - - /// - /// Gets or sets the item ids. - /// - /// The item ids. - [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; } - - /// - /// Gets or sets the video types. - /// - /// The video types. - [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; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the min offical rating. - /// - /// The min offical rating. - [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; } - - /// - /// Gets or sets the video formats. - /// - /// The video formats. - [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; } - - /// - /// Gets or sets the series status. - /// - /// The series status. - [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() - : VideoTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(v => Enum.Parse(v, true)).ToArray(); - } - - /// - /// Gets the filters. - /// - /// IEnumerable{ItemFilter}. - public ItemFilter[] GetFilters() - { - var val = Filters; - - return string.IsNullOrEmpty(val) - ? Array.Empty() - : val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(v => Enum.Parse(v, true)).ToArray(); - } - - /// - /// Gets the image types. - /// - /// IEnumerable{ImageType}. - public ImageType[] GetImageTypes() - { - var val = ImageTypes; - - return string.IsNullOrEmpty(val) - ? Array.Empty() - : val.Split(',').Select(v => Enum.Parse(v, true)).ToArray(); - } - - /// - /// Gets the order by. - /// - /// IEnumerable{ItemSortBy}. - public ValueTuple[] GetOrderBy() - { - return GetOrderBy(SortBy, SortOrder); - } - - public static ValueTuple[] GetOrderBy(string sortBy, string requestedSortOrder) - { - var val = sortBy; - - if (string.IsNullOrEmpty(val)) - { - return Array.Empty>(); - } - - var vals = val.Split(','); - if (string.IsNullOrWhiteSpace(requestedSortOrder)) - { - requestedSortOrder = "Ascending"; - } - - var sortOrders = requestedSortOrder.Split(','); - - var result = new ValueTuple[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(vals[i], sortOrder); - } - - return result; - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs deleted file mode 100644 index 7bdfbac981..0000000000 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetGenres. - /// - [Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")] - public class GetGenres : GetItemsByName - { - } - - /// - /// Class GetGenre. - /// - [Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")] - public class GetGenre : IReturn - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - } - - /// - /// Class GenresService. - /// - [Authenticated] - public class GenresService : BaseItemsByNameService - { - public GenresService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IUserDataManager userDataRepository, - IDtoService dtoService, - IAuthorizationContext authorizationContext) - : base( - logger, - serverConfigurationManager, - httpResultFactory, - userManager, - libraryManager, - userDataRepository, - dtoService, - authorizationContext) - { - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetGenre request) - { - var result = GetItem(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the item. - /// - /// The request. - /// Task{BaseItemDto}. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Tuple{System.StringFunc{System.Int32}}}. - protected override IEnumerable GetAllItems(GetItemsByName request, IList items) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs deleted file mode 100644 index 7efe0552c6..0000000000 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetItems. - /// - [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> - { - } - - [Route("/Users/{UserId}/Items/Resume", "GET", Summary = "Gets items based on a query.")] - public class GetResumeItems : BaseItemsRequest, IReturn> - { - } - - /// - /// Class ItemsService. - /// - [Authenticated] - public class ItemsService : BaseApiService - { - /// - /// The _user manager. - /// - private readonly IUserManager _userManager; - - /// - /// The _library manager. - /// - private readonly ILibraryManager _libraryManager; - private readonly ILocalizationManager _localization; - - private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; - - /// - /// Initializes a new instance of the class. - /// - /// The user manager. - /// The library manager. - /// The localization. - /// The dto service. - public ItemsService( - ILogger 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(); - - 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 - { - StartIndex = request.StartIndex.GetValueOrDefault(), - TotalRecordCount = itemsResult.TotalRecordCount, - Items = returnItems - }; - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetItems request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - var result = GetItems(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the items. - /// - /// The request. - private QueryResult 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 - { - StartIndex = request.StartIndex.GetValueOrDefault(), - TotalRecordCount = result.TotalRecordCount, - Items = dtoList - }; - } - - /// - /// Gets the items to serialize. - /// - private QueryResult 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 - { - Items = Array.Empty(), - 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 - { - 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(ItemSortBy.ProductionYear, SortOrder.Descending), - new ValueTuple(ItemSortBy.SortName, SortOrder.Ascending) - }; - } - } - - return query; - } - } - - /// - /// Class DateCreatedComparer. - /// - public class DateCreatedComparer : IComparer - { - /// - /// Compares the specified x. - /// - /// The x. - /// The y. - /// System.Int32. - public int Compare(BaseItem x, BaseItem y) - { - return x.DateCreated.CompareTo(y.DateCreated); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs deleted file mode 100644 index 7924339ed3..0000000000 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetPersons. - /// - [Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")] - public class GetPersons : GetItemsByName - { - } - - /// - /// Class GetPerson. - /// - [Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")] - public class GetPerson : IReturn - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The person name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - } - - /// - /// Class PersonsService. - /// - [Authenticated] - public class PersonsService : BaseItemsByNameService - { - public PersonsService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IUserDataManager userDataRepository, - IDtoService dtoService, - IAuthorizationContext authorizationContext) - : base( - logger, - serverConfigurationManager, - httpResultFactory, - userManager, - libraryManager, - userDataRepository, - dtoService, - authorizationContext) - { - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetPerson request) - { - var result = GetItem(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the item. - /// - /// The request. - /// Task{BaseItemDto}. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetPersons request) - { - return GetResultSlim(request); - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Tuple{System.StringFunc{System.Int32}}}. - protected override IEnumerable GetAllItems(GetItemsByName request, IList 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() - }; - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs deleted file mode 100644 index d809cc2e79..0000000000 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ /dev/null @@ -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 -{ - /// - /// Class MarkPlayedItem. - /// - [Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")] - public class MarkPlayedItem : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - } - - /// - /// Class MarkUnplayedItem. - /// - [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")] - public class MarkUnplayedItem : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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 - { - } - - /// - /// Class OnPlaybackStart. - /// - [Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")] - public class OnPlaybackStart : IReturnVoid - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - } - - /// - /// Class OnPlaybackProgress. - /// - [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")] - public class OnPlaybackProgress : IReturnVoid - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - - /// - /// Gets or sets the position ticks. - /// - /// The position ticks. - [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; } - } - - /// - /// Class OnPlaybackStopped. - /// - [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")] - public class OnPlaybackStopped : IReturnVoid - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - - /// - /// Gets or sets the position ticks. - /// - /// The position ticks. - [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 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; - } - - /// - /// Posts the specified request. - /// - /// The request. - 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; - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - - /// - /// Deletes the specified request. - /// - /// The request. - 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; - } - - /// - /// Updates the played status. - /// - /// The user. - /// The item id. - /// if set to true [was played]. - /// The date played. - /// Task. - 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); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs deleted file mode 100644 index 66350955f5..0000000000 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetStudios. - /// - [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")] - public class GetStudios : GetItemsByName - { - } - - /// - /// Class GetStudio. - /// - [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")] - public class GetStudio : IReturn - { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "Name", Description = "The studio name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - } - - /// - /// Class StudiosService. - /// - [Authenticated] - public class StudiosService : BaseItemsByNameService - { - public StudiosService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IUserDataManager userDataRepository, - IDtoService dtoService, - IAuthorizationContext authorizationContext) - : base( - logger, - serverConfigurationManager, - httpResultFactory, - userManager, - libraryManager, - userDataRepository, - dtoService, - authorizationContext) - { - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetStudio request) - { - var result = GetItem(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the item. - /// - /// The request. - /// Task{BaseItemDto}. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Tuple{System.StringFunc{System.Int32}}}. - protected override IEnumerable GetAllItems(GetItemsByName request, IList items) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs deleted file mode 100644 index f9cbba4104..0000000000 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetItem. - /// - [Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")] - public class GetItem : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class GetItem. - /// - [Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")] - public class GetRootFolder : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - } - - /// - /// Class GetIntros. - /// - [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")] - public class GetIntros : IReturn> - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the item id. - /// - /// The item id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class MarkFavoriteItem. - /// - [Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")] - public class MarkFavoriteItem : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid Id { get; set; } - } - - /// - /// Class UnmarkFavoriteItem. - /// - [Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")] - public class UnmarkFavoriteItem : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid Id { get; set; } - } - - /// - /// Class ClearUserItemRating. - /// - [Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")] - public class DeleteUserItemRating : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid Id { get; set; } - } - - /// - /// Class UpdateUserItemRating. - /// - [Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")] - public class UpdateUserItemRating : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid Id { get; set; } - - /// - /// Gets or sets a value indicating whether this is likes. - /// - /// true if likes; otherwise, false. - [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; } - } - - /// - /// Class GetLocalTrailers. - /// - [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")] - public class GetLocalTrailers : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - /// - /// Class GetSpecialFeatures. - /// - [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")] - public class GetSpecialFeatures : IReturn - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - [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, IHasDtoOptions - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; - } - } - - /// - /// Class UserLibraryService. - /// - [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 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; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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(); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public async Task 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); - } - } - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public async Task 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 - { - Items = dtos, - TotalRecordCount = dtos.Length - }; - - return ToOptimizedResult(result); - } - - /// - /// Posts the specified request. - /// - /// The request. - public object Post(MarkFavoriteItem request) - { - var dto = MarkFavorite(request.UserId, request.Id, true); - - return ToOptimizedResult(dto); - } - - /// - /// Deletes the specified request. - /// - /// The request. - public object Delete(UnmarkFavoriteItem request) - { - var dto = MarkFavorite(request.UserId, request.Id, false); - - return ToOptimizedResult(dto); - } - - /// - /// Marks the favorite. - /// - /// The user id. - /// The item id. - /// if set to true [is favorite]. - 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); - } - - /// - /// Deletes the specified request. - /// - /// The request. - public object Delete(DeleteUserItemRating request) - { - var dto = UpdateUserItemRating(request.UserId, request.Id, null); - - return ToOptimizedResult(dto); - } - - /// - /// Posts the specified request. - /// - /// The request. - public object Post(UpdateUserItemRating request) - { - var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes); - - return ToOptimizedResult(dto); - } - - /// - /// Updates the user item rating. - /// - /// The user id. - /// The item id. - /// if set to true [likes]. - 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); - } - } -} diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs deleted file mode 100644 index 6f1620dddf..0000000000 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ /dev/null @@ -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> - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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 - { - /// - /// Gets or sets the user id. - /// - /// The user id. - [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 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 - { - 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() - .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; } - } -} diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs deleted file mode 100644 index 0523f89fa7..0000000000 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetYears. - /// - [Route("/Years", "GET", Summary = "Gets all years from a given item, folder, or the entire library")] - public class GetYears : GetItemsByName - { - } - - /// - /// Class GetYear. - /// - [Route("/Years/{Year}", "GET", Summary = "Gets a year")] - public class GetYear : IReturn - { - /// - /// Gets or sets the year. - /// - /// The year. - [ApiMember(Name = "Year", Description = "The year", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] - public int Year { get; set; } - - /// - /// Gets or sets the user id. - /// - /// The user id. - [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; } - } - - /// - /// Class YearsService. - /// - [Authenticated] - public class YearsService : BaseItemsByNameService - { - public YearsService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IUserDataManager userDataRepository, - IDtoService dtoService, - IAuthorizationContext authorizationContext) - : base( - logger, - serverConfigurationManager, - httpResultFactory, - userManager, - libraryManager, - userDataRepository, - dtoService, - authorizationContext) - { - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetYear request) - { - var result = GetItem(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets the item. - /// - /// The request. - /// Task{BaseItemDto}. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetYears request) - { - var result = GetResult(request); - - return ToOptimizedResult(result); - } - - /// - /// Gets all items. - /// - /// The request. - /// The items. - /// IEnumerable{Tuple{System.StringFunc{System.Int32}}}. - protected override IEnumerable GetAllItems(GetItemsByName request, IList items) - { - return items - .Select(i => i.ProductionYear ?? 0) - .Where(i => i > 0) - .Distinct() - .Select(year => LibraryManager.GetYear(year)); - } - } -} diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs deleted file mode 100644 index 6e9d788dc1..0000000000 --- a/MediaBrowser.Api/UserService.cs +++ /dev/null @@ -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 -{ - /// - /// Class GetUsers. - /// - [Route("/Users", "GET", Summary = "Gets a list of users")] - [Authenticated] - public class GetUsers : IReturn - { - [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 - { - } - - /// - /// Class GetUser. - /// - [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")] - [Authenticated(EscapeParentalControl = true)] - public class GetUser : IReturn - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid Id { get; set; } - } - - /// - /// Class DeleteUser. - /// - [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")] - [Authenticated(Roles = "Admin")] - public class DeleteUser : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public Guid Id { get; set; } - } - - /// - /// Class AuthenticateUser. - /// - [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")] - public class AuthenticateUser : IReturn - { - /// - /// Gets or sets the id. - /// - /// The id. - [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; } - - /// - /// Gets or sets the password. - /// - /// The password. - [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] - public string Password { get; set; } - } - - /// - /// Class AuthenticateUser. - /// - [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")] - public class AuthenticateUserByName : IReturn - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Username", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] - public string Username { get; set; } - - /// - /// Gets or sets the password. - /// - /// The password. - [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; } - } - - /// - /// Class UpdateUserPassword. - /// - [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")] - [Authenticated] - public class UpdateUserPassword : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - public Guid Id { get; set; } - - /// - /// Gets or sets the password. - /// - /// The password. - public string CurrentPassword { get; set; } - - public string CurrentPw { get; set; } - - public string NewPw { get; set; } - - /// - /// Gets or sets a value indicating whether [reset password]. - /// - /// true if [reset password]; otherwise, false. - public bool ResetPassword { get; set; } - } - - /// - /// Class UpdateUserEasyPassword. - /// - [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")] - [Authenticated] - public class UpdateUserEasyPassword : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - public Guid Id { get; set; } - - /// - /// Gets or sets the new password. - /// - /// The new password. - public string NewPassword { get; set; } - - public string NewPw { get; set; } - - /// - /// Gets or sets a value indicating whether [reset password]. - /// - /// true if [reset password]; otherwise, false. - public bool ResetPassword { get; set; } - } - - /// - /// Class UpdateUser. - /// - [Route("/Users/{Id}", "POST", Summary = "Updates a user")] - [Authenticated] - public class UpdateUser : UserDto, IReturnVoid - { - } - - /// - /// Class UpdateUser. - /// - [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; } - } - - /// - /// Class UpdateUser. - /// - [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; } - } - - /// - /// Class CreateUser. - /// - [Route("/Users/New", "POST", Summary = "Creates a user")] - [Authenticated(Roles = "Admin")] - public class CreateUserByName : IReturn - { - [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 - { - [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 - { - [ApiMember(Name = "Pin", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")] - public string Pin { get; set; } - } - - /// - /// Class UsersService. - /// - public class UserService : BaseApiService - { - /// - /// The user manager. - /// - private readonly IUserManager _userManager; - private readonly ISessionManager _sessionMananger; - private readonly INetworkManager _networkManager; - private readonly IDeviceManager _deviceManager; - private readonly IAuthorizationContext _authContext; - - public UserService( - ILogger 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - 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); - } - - /// - /// Deletes the specified request. - /// - /// The request. - 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; - } - - /// - /// Posts the specified request. - /// - /// The request. - 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 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); - } - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - } - - /// - /// Posts the specified request. - /// - /// The request. - 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); - } - } - - /// - /// Posts the specified request. - /// - /// The request. - /// System.Object. - public async Task 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 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 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); - } - } -}