aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrobibero <cody@robibe.ro>2020-07-20 14:43:54 -0600
committercrobibero <cody@robibe.ro>2020-07-20 14:43:54 -0600
commit5c66f9e4716961dc40e0444c7d261dfd2e5841d7 (patch)
tree762c571faa5715ffd0062b790099b1113faccc37
parent13850644973b1223bbeb2271e42ad252d43a10bf (diff)
changes from merge
-rw-r--r--Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs1
-rw-r--r--Jellyfin.Api/Controllers/ActivityLogController.cs10
-rw-r--r--Jellyfin.Api/Controllers/DashboardController.cs1
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs1
-rw-r--r--Jellyfin.Api/Controllers/ItemRefreshController.cs1
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs1
-rw-r--r--Jellyfin.Api/Controllers/LibraryStructureController.cs1
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs1
-rw-r--r--Jellyfin.Api/Controllers/NotificationsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/PackageController.cs38
-rw-r--r--Jellyfin.Api/Controllers/PluginsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs9
-rw-r--r--Jellyfin.Api/Helpers/TranscodingJobHelper.cs1
-rw-r--r--Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs3
-rw-r--r--MediaBrowser.Api/ChannelService.cs340
-rw-r--r--MediaBrowser.Api/ConfigurationService.cs144
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs103
-rw-r--r--MediaBrowser.Api/DisplayPreferencesService.cs101
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs285
-rw-r--r--MediaBrowser.Api/FilterService.cs248
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs277
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs296
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs336
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs1124
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs412
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs1287
-rw-r--r--MediaBrowser.Api/LocalizationService.cs111
-rw-r--r--MediaBrowser.Api/Movies/CollectionService.cs104
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs414
-rw-r--r--MediaBrowser.Api/Movies/TrailersService.cs88
-rw-r--r--MediaBrowser.Api/Music/AlbumsService.cs132
-rw-r--r--MediaBrowser.Api/Music/InstantMixService.cs196
-rw-r--r--MediaBrowser.Api/PackageService.cs197
-rw-r--r--MediaBrowser.Api/PlaylistService.cs216
-rw-r--r--MediaBrowser.Api/PluginService.cs277
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs234
-rw-r--r--MediaBrowser.Api/SearchService.cs332
-rw-r--r--MediaBrowser.Api/Sessions/SessionService.cs499
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs302
-rw-r--r--MediaBrowser.Api/SuggestionsService.cs103
-rw-r--r--MediaBrowser.Api/System/ActivityLogService.cs69
-rw-r--r--MediaBrowser.Api/System/SystemService.cs221
-rw-r--r--MediaBrowser.Api/TvShowsService.cs497
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs143
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs388
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs478
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs140
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs514
-rw-r--r--MediaBrowser.Api/UserLibrary/PersonsService.cs146
-rw-r--r--MediaBrowser.Api/UserLibrary/PlaystateService.cs456
-rw-r--r--MediaBrowser.Api/UserLibrary/StudiosService.cs132
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs575
-rw-r--r--MediaBrowser.Api/UserLibrary/UserViewsService.cs148
-rw-r--r--MediaBrowser.Api/UserLibrary/YearsService.cs131
-rw-r--r--MediaBrowser.Api/UserService.cs598
56 files changed, 43 insertions, 12822 deletions
diff --git a/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs b/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs
index fcfa55dfe..b61680ab1 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 c287d1a77..12ea24973 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
/// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="minDate">Optional. The minimum date. Format = ISO.</param>
+ /// <param name="hasUserId">Optional. Filter log entries if it has user id, or not.</param>
/// <response code="200">Activity log returned.</response>
/// <returns>A <see cref="QueryResult{ActivityLogEntry}"/> containing the log entries.</returns>
[HttpGet("Entries")]
@@ -42,10 +42,14 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryResult<ActivityLogEntry>> GetLogEntries(
[FromQuery] int? startIndex,
[FromQuery] int? limit,
- [FromQuery] DateTime? minDate)
+ [FromQuery] DateTime? minDate,
+ [FromQuery] bool? hasUserId)
{
var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
- entries => entries.Where(entry => entry.DateCreated >= minDate));
+ entries => entries.Where(entry => entry.DateCreated >= minDate
+ && (!hasUserId.HasValue || (hasUserId.Value
+ ? entry.UserId != Guid.Empty
+ : entry.UserId == Guid.Empty))));
return _activityManager.GetPagedResult(filterFunc, startIndex, limit);
}
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs
index 699ef6bf7..e033c50d5 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 288d4c545..9ba5e1161 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 3801ce5b7..4697d869d 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 2466b2ac8..5ad466c55 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 881d3f192..d3537a7a7 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 144a7b554..a9af1a2c3 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 02aa39b24..1bb39b5f7 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 68ae05658..a6c552790 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;
/// <summary>
/// Initializes a new instance of the <see cref="PackageController"/> class.
/// </summary>
- /// <param name="installationManager">Instance of <see cref="IInstallationManager"/>Installation Manager.</param>
- public PackageController(IInstallationManager installationManager)
+ /// <param name="installationManager">Instance of the <see cref="IInstallationManager"/> interface.</param>
+ /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+ public PackageController(IInstallationManager installationManager, IServerConfigurationManager serverConfigurationManager)
{
_installationManager = installationManager;
+ _serverConfigurationManager = serverConfigurationManager;
}
/// <summary>
@@ -110,11 +114,39 @@ namespace Jellyfin.Api.Controllers
[HttpDelete("/Installing/{packageId}")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public IActionResult CancelPackageInstallation(
+ public ActionResult CancelPackageInstallation(
[FromRoute] [Required] Guid packageId)
{
_installationManager.CancelInstallation(packageId);
return NoContent();
}
+
+ /// <summary>
+ /// Gets all package repositories.
+ /// </summary>
+ /// <response code="200">Package repositories returned.</response>
+ /// <returns>An <see cref="OkResult"/> containing the list of package repositories.</returns>
+ [HttpGet("/Repositories")]
+ [Authorize(Policy = Policies.DefaultAuthorization)]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public ActionResult<IEnumerable<RepositoryInfo>> GetRepositories()
+ {
+ return _serverConfigurationManager.Configuration.PluginRepositories;
+ }
+
+ /// <summary>
+ /// Sets the enabled and existing package repositories.
+ /// </summary>
+ /// <param name="repositoryInfos">The list of package repositories.</param>
+ /// <response code="204">Package repositories saved.</response>
+ /// <returns>A <see cref="NoContentResult"/>.</returns>
+ [HttpOptions("/Repositories")]
+ [Authorize(Policy = Policies.DefaultAuthorization)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ public ActionResult SetRepositories([FromBody] List<RepositoryInfo> repositoryInfos)
+ {
+ _serverConfigurationManager.Configuration.PluginRepositories = repositoryInfos;
+ return NoContent();
+ }
}
}
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index 056395a51..48bb867ac 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 e5b043621..d54bc10c0 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 24194dcc2..8038ca044 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 44f662e6e..34b371d3f 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 dcc322470..b9507a4e5 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 8c336b1c9..000000000
--- 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<QueryResult<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "SupportsLatestItems", Description = "Optional. Filter by channels that support getting latest items.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? SupportsLatestItems { get; set; }
-
- public bool? SupportsMediaDeletion { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is favorite.
- /// </summary>
- /// <value><c>null</c> if [is favorite] contains no value, <c>true</c> if [is favorite]; otherwise, <c>false</c>.</value>
- public bool? IsFavorite { get; set; }
- }
-
- [Route("/Channels/{Id}/Features", "GET", Summary = "Gets features for a channel")]
- public class GetChannelFeatures : IReturn<ChannelFeatures>
- {
- [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Channels/Features", "GET", Summary = "Gets features for a channel")]
- public class GetAllChannelFeatures : IReturn<ChannelFeatures[]>
- {
- }
-
- [Route("/Channels/{Id}/Items", "GET", Summary = "Gets channel items")]
- public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
- {
- [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "FolderId", Description = "Folder Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string FolderId { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SortOrder { get; set; }
-
- [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Filters { get; set; }
-
- [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string SortBy { get; set; }
-
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- /// <summary>
- /// Gets the filters.
- /// </summary>
- /// <returns>IEnumerable{ItemFilter}.</returns>
- public IEnumerable<ItemFilter> GetFilters()
- {
- var val = Filters;
-
- return string.IsNullOrEmpty(val)
- ? Array.Empty<ItemFilter>()
- : val.Split(',').Select(v => Enum.Parse<ItemFilter>(v, true));
- }
-
- /// <summary>
- /// Gets the order by.
- /// </summary>
- /// <returns>IEnumerable{ItemSortBy}.</returns>
- public ValueTuple<string, SortOrder>[] GetOrderBy()
- {
- return BaseItemsRequest.GetOrderBy(SortBy, SortOrder);
- }
- }
-
- [Route("/Channels/Items/Latest", "GET", Summary = "Gets channel items")]
- public class GetLatestChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Filters { get; set; }
-
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ChannelIds { get; set; }
-
- /// <summary>
- /// Gets the filters.
- /// </summary>
- /// <returns>IEnumerable{ItemFilter}.</returns>
- public IEnumerable<ItemFilter> GetFilters()
- {
- return string.IsNullOrEmpty(Filters)
- ? Array.Empty<ItemFilter>()
- : Filters.Split(',').Select(v => Enum.Parse<ItemFilter>(v, true));
- }
- }
-
- [Authenticated]
- public class ChannelService : BaseApiService
- {
- private readonly IChannelManager _channelManager;
- private IUserManager _userManager;
-
- public ChannelService(
- ILogger<ChannelService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IChannelManager channelManager,
- IUserManager userManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _channelManager = channelManager;
- _userManager = userManager;
- }
-
- public object Get(GetAllChannelFeatures request)
- {
- var result = _channelManager.GetAllChannelFeatures();
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetChannelFeatures request)
- {
- var result = _channelManager.GetChannelFeatures(request.Id);
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetChannels request)
- {
- var result = _channelManager.GetChannels(new ChannelQuery
- {
- Limit = request.Limit,
- StartIndex = request.StartIndex,
- UserId = request.UserId,
- SupportsLatestItems = request.SupportsLatestItems,
- SupportsMediaDeletion = request.SupportsMediaDeletion,
- IsFavorite = request.IsFavorite
- });
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetChannelItems request)
- {
- var user = request.UserId.Equals(Guid.Empty)
- ? null
- : _userManager.GetUserById(request.UserId);
-
- var query = new InternalItemsQuery(user)
- {
- Limit = request.Limit,
- StartIndex = request.StartIndex,
- ChannelIds = new[] { new Guid(request.Id) },
- ParentId = string.IsNullOrWhiteSpace(request.FolderId) ? Guid.Empty : new Guid(request.FolderId),
- OrderBy = request.GetOrderBy(),
- DtoOptions = new Controller.Dto.DtoOptions
- {
- Fields = request.GetItemFields()
- }
- };
-
- foreach (var filter in request.GetFilters())
- {
- switch (filter)
- {
- case ItemFilter.Dislikes:
- query.IsLiked = false;
- break;
- case ItemFilter.IsFavorite:
- query.IsFavorite = true;
- break;
- case ItemFilter.IsFavoriteOrLikes:
- query.IsFavoriteOrLiked = true;
- break;
- case ItemFilter.IsFolder:
- query.IsFolder = true;
- break;
- case ItemFilter.IsNotFolder:
- query.IsFolder = false;
- break;
- case ItemFilter.IsPlayed:
- query.IsPlayed = true;
- break;
- case ItemFilter.IsResumable:
- query.IsResumable = true;
- break;
- case ItemFilter.IsUnplayed:
- query.IsPlayed = false;
- break;
- case ItemFilter.Likes:
- query.IsLiked = true;
- break;
- }
- }
-
- var result = await _channelManager.GetChannelItems(query, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetLatestChannelItems request)
- {
- var user = request.UserId.Equals(Guid.Empty)
- ? null
- : _userManager.GetUserById(request.UserId);
-
- var query = new InternalItemsQuery(user)
- {
- Limit = request.Limit,
- StartIndex = request.StartIndex,
- ChannelIds = (request.ChannelIds ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToArray(),
- DtoOptions = new Controller.Dto.DtoOptions
- {
- Fields = request.GetItemFields()
- }
- };
-
- foreach (var filter in request.GetFilters())
- {
- switch (filter)
- {
- case ItemFilter.Dislikes:
- query.IsLiked = false;
- break;
- case ItemFilter.IsFavorite:
- query.IsFavorite = true;
- break;
- case ItemFilter.IsFavoriteOrLikes:
- query.IsFavoriteOrLiked = true;
- break;
- case ItemFilter.IsFolder:
- query.IsFolder = true;
- break;
- case ItemFilter.IsNotFolder:
- query.IsFolder = false;
- break;
- case ItemFilter.IsPlayed:
- query.IsPlayed = true;
- break;
- case ItemFilter.IsResumable:
- query.IsResumable = true;
- break;
- case ItemFilter.IsUnplayed:
- query.IsPlayed = false;
- break;
- case ItemFilter.Likes:
- query.IsLiked = true;
- break;
- }
- }
-
- var result = await _channelManager.GetLatestChannelItems(query, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
- }
-}
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
deleted file mode 100644
index 19369ccca..000000000
--- 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
-{
- /// <summary>
- /// Class GetConfiguration.
- /// </summary>
- [Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
- [Authenticated]
- public class GetConfiguration : IReturn<ServerConfiguration>
- {
- }
-
- [Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")]
- [Authenticated(AllowBeforeStartupWizard = true)]
- public class GetNamedConfiguration
- {
- [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Key { get; set; }
- }
-
- /// <summary>
- /// Class UpdateConfiguration.
- /// </summary>
- [Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
- [Authenticated(Roles = "Admin")]
- public class UpdateConfiguration : ServerConfiguration, IReturnVoid
- {
- }
-
- [Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")]
- [Authenticated(Roles = "Admin")]
- public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream
- {
- [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Key { get; set; }
-
- public Stream RequestStream { get; set; }
- }
-
- [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
- [Authenticated(Roles = "Admin")]
- public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
- {
- }
-
- [Route("/System/MediaEncoder/Path", "POST", Summary = "Updates the path to the media encoder")]
- [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
- public class UpdateMediaEncoderPath : IReturnVoid
- {
- [ApiMember(Name = "Path", Description = "Path", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Path { get; set; }
- [ApiMember(Name = "PathType", Description = "PathType", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string PathType { get; set; }
- }
-
- public class ConfigurationService : BaseApiService
- {
- /// <summary>
- /// The _json serializer.
- /// </summary>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// The _configuration manager.
- /// </summary>
- private readonly IServerConfigurationManager _configurationManager;
-
- private readonly IMediaEncoder _mediaEncoder;
-
- public ConfigurationService(
- ILogger<ConfigurationService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IJsonSerializer jsonSerializer,
- IServerConfigurationManager configurationManager,
- IMediaEncoder mediaEncoder)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _jsonSerializer = jsonSerializer;
- _configurationManager = configurationManager;
- _mediaEncoder = mediaEncoder;
- }
-
- public void Post(UpdateMediaEncoderPath request)
- {
- _mediaEncoder.UpdateEncoderPath(request.Path, request.PathType);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetConfiguration request)
- {
- return ToOptimizedResult(_configurationManager.Configuration);
- }
-
- public object Get(GetNamedConfiguration request)
- {
- var result = _configurationManager.GetConfiguration(request.Key);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified configuraiton.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(UpdateConfiguration request)
- {
- // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration
- var json = _jsonSerializer.SerializeToString(request);
-
- var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json);
-
- _configurationManager.ReplaceConfiguration(config);
- }
-
- public async Task Post(UpdateNamedConfiguration request)
- {
- var key = GetPathValue(2).ToString();
-
- var configurationType = _configurationManager.GetConfigurationType(key);
- var configuration = await _jsonSerializer.DeserializeFromStreamAsync(request.RequestStream, configurationType).ConfigureAwait(false);
-
- _configurationManager.SaveConfiguration(key, configuration);
- }
-
- public object Get(GetDefaultMetadataOptions request)
- {
- return ToOptimizedResult(new MetadataOptions());
- }
- }
-}
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
deleted file mode 100644
index 18860983e..000000000
--- 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<QueryResult<DeviceInfo>>
- {
- }
-
- [Route("/Devices/Info", "GET", Summary = "Gets info for a device")]
- [Authenticated(Roles = "Admin")]
- public class GetDeviceInfo : IReturn<DeviceInfo>
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Devices/Options", "GET", Summary = "Gets options for a device")]
- [Authenticated(Roles = "Admin")]
- public class GetDeviceOptions : IReturn<DeviceOptions>
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Devices", "DELETE", Summary = "Deletes a device")]
- public class DeleteDevice
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Devices/Options", "POST", Summary = "Updates device options")]
- [Authenticated(Roles = "Admin")]
- public class PostDeviceOptions : DeviceOptions, IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- public class DeviceService : BaseApiService
- {
- private readonly IDeviceManager _deviceManager;
- private readonly IAuthenticationRepository _authRepo;
- private readonly ISessionManager _sessionManager;
-
- public DeviceService(
- ILogger<DeviceService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IDeviceManager deviceManager,
- IAuthenticationRepository authRepo,
- ISessionManager sessionManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _deviceManager = deviceManager;
- _authRepo = authRepo;
- _sessionManager = sessionManager;
- }
-
- public void Post(PostDeviceOptions request)
- {
- _deviceManager.UpdateDeviceOptions(request.Id, request);
- }
-
- public object Get(GetDevices request)
- {
- return ToOptimizedResult(_deviceManager.GetDevices(request));
- }
-
- public object Get(GetDeviceInfo request)
- {
- return _deviceManager.GetDevice(request.Id);
- }
-
- public object Get(GetDeviceOptions request)
- {
- return _deviceManager.GetDeviceOptions(request.Id);
- }
-
- public void Delete(DeleteDevice request)
- {
- var sessions = _authRepo.Get(new AuthenticationInfoQuery
- {
- DeviceId = request.Id
- }).Items;
-
- foreach (var session in sessions)
- {
- _sessionManager.Logout(session);
- }
- }
- }
-}
diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs
deleted file mode 100644
index c3ed40ad3..000000000
--- 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
-{
- /// <summary>
- /// Class UpdateDisplayPreferences.
- /// </summary>
- [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")]
- public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "DisplayPreferencesId", Description = "DisplayPreferences Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string DisplayPreferencesId { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]
- public class GetDisplayPreferences : IReturn<DisplayPreferences>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string UserId { get; set; }
-
- [ApiMember(Name = "Client", Description = "Client", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Client { get; set; }
- }
-
- /// <summary>
- /// Class DisplayPreferencesService.
- /// </summary>
- [Authenticated]
- public class DisplayPreferencesService : BaseApiService
- {
- /// <summary>
- /// The _display preferences manager.
- /// </summary>
- private readonly IDisplayPreferencesRepository _displayPreferencesManager;
- /// <summary>
- /// The _json serializer.
- /// </summary>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DisplayPreferencesService" /> class.
- /// </summary>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="displayPreferencesManager">The display preferences manager.</param>
- public DisplayPreferencesService(
- ILogger<DisplayPreferencesService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IJsonSerializer jsonSerializer,
- IDisplayPreferencesRepository displayPreferencesManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _jsonSerializer = jsonSerializer;
- _displayPreferencesManager = displayPreferencesManager;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Get(GetDisplayPreferences request)
- {
- var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(UpdateDisplayPreferences request)
- {
- // Serialize to json and then back so that the core doesn't see the request dto type
- var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
-
- _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None);
- }
- }
-}
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
deleted file mode 100644
index 720a71025..000000000
--- 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
-{
- /// <summary>
- /// Class GetDirectoryContents.
- /// </summary>
- [Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")]
- public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
- {
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Path { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [include files].
- /// </summary>
- /// <value><c>true</c> if [include files]; otherwise, <c>false</c>.</value>
- [ApiMember(Name = "IncludeFiles", Description = "An optional filter to include or exclude files from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool IncludeFiles { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [include directories].
- /// </summary>
- /// <value><c>true</c> if [include directories]; otherwise, <c>false</c>.</value>
- [ApiMember(Name = "IncludeDirectories", Description = "An optional filter to include or exclude folders from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool IncludeDirectories { get; set; }
- }
-
- [Route("/Environment/ValidatePath", "POST", Summary = "Gets the contents of a given directory in the file system")]
- public class ValidatePath
- {
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Path { get; set; }
-
- public bool ValidateWriteable { get; set; }
-
- public bool? IsFile { get; set; }
- }
-
- [Obsolete]
- [Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
- public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
- {
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Path { get; set; }
- }
-
- /// <summary>
- /// Class GetDrives.
- /// </summary>
- [Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")]
- public class GetDrives : IReturn<List<FileSystemEntryInfo>>
- {
- }
-
- /// <summary>
- /// Class GetNetworkComputers.
- /// </summary>
- [Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")]
- public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
- {
- }
-
- [Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")]
- public class GetParentPath : IReturn<string>
- {
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Path { get; set; }
- }
-
- public class DefaultDirectoryBrowserInfo
- {
- public string Path { get; set; }
- }
-
- [Route("/Environment/DefaultDirectoryBrowser", "GET", Summary = "Gets the parent path of a given path")]
- public class GetDefaultDirectoryBrowser : IReturn<DefaultDirectoryBrowserInfo>
- {
- }
-
- /// <summary>
- /// Class EnvironmentService.
- /// </summary>
- [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
- public class EnvironmentService : BaseApiService
- {
- private const char UncSeparator = '\\';
- private const string UncSeparatorString = "\\";
-
- /// <summary>
- /// The _network manager.
- /// </summary>
- private readonly INetworkManager _networkManager;
- private readonly IFileSystem _fileSystem;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="EnvironmentService" /> class.
- /// </summary>
- /// <param name="networkManager">The network manager.</param>
- public EnvironmentService(
- ILogger<EnvironmentService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- INetworkManager networkManager,
- IFileSystem fileSystem)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _networkManager = networkManager;
- _fileSystem = fileSystem;
- }
-
- public void Post(ValidatePath request)
- {
- if (request.IsFile.HasValue)
- {
- if (request.IsFile.Value)
- {
- if (!File.Exists(request.Path))
- {
- throw new FileNotFoundException("File not found", request.Path);
- }
- }
- else
- {
- if (!Directory.Exists(request.Path))
- {
- throw new FileNotFoundException("File not found", request.Path);
- }
- }
- }
-
- else
- {
- if (!File.Exists(request.Path) && !Directory.Exists(request.Path))
- {
- throw new FileNotFoundException("Path not found", request.Path);
- }
-
- if (request.ValidateWriteable)
- {
- EnsureWriteAccess(request.Path);
- }
- }
- }
-
- protected void EnsureWriteAccess(string path)
- {
- var file = Path.Combine(path, Guid.NewGuid().ToString());
-
- File.WriteAllText(file, string.Empty);
- _fileSystem.DeleteFile(file);
- }
-
- public object Get(GetDefaultDirectoryBrowser request) =>
- ToOptimizedResult(new DefaultDirectoryBrowserInfo { Path = null });
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetDirectoryContents request)
- {
- var path = request.Path;
-
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException(nameof(Path));
- }
-
- var networkPrefix = UncSeparatorString + UncSeparatorString;
-
- if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase)
- && path.LastIndexOf(UncSeparator) == 1)
- {
- return ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
- }
-
- return ToOptimizedResult(GetFileSystemEntries(request).ToList());
- }
-
- [Obsolete]
- public object Get(GetNetworkShares request)
- => ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetDrives request)
- {
- var result = GetDrives().ToList();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the list that is returned when an empty path is supplied.
- /// </summary>
- /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
- private IEnumerable<FileSystemEntryInfo> GetDrives()
- {
- return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Directory));
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetNetworkDevices request)
- => ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
-
- /// <summary>
- /// Gets the file system entries.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
- private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
- {
- var entries = _fileSystem.GetFileSystemEntries(request.Path).OrderBy(i => i.FullName).Where(i =>
- {
- var isDirectory = i.IsDirectory;
-
- if (!request.IncludeFiles && !isDirectory)
- {
- return false;
- }
-
- return request.IncludeDirectories || !isDirectory;
- });
-
- return entries.Select(f => new FileSystemEntryInfo(f.Name, f.FullName, f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File));
- }
-
- public object Get(GetParentPath request)
- {
- var parent = Path.GetDirectoryName(request.Path);
-
- if (string.IsNullOrEmpty(parent))
- {
- // Check if unc share
- var index = request.Path.LastIndexOf(UncSeparator);
-
- if (index != -1 && request.Path.IndexOf(UncSeparator) == 0)
- {
- parent = request.Path.Substring(0, index);
-
- if (string.IsNullOrWhiteSpace(parent.TrimStart(UncSeparator)))
- {
- parent = null;
- }
- }
- }
-
- return parent;
- }
- }
-}
diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs
deleted file mode 100644
index dcfdcbfed..000000000
--- 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<QueryFiltersLegacy>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string IncludeItemTypes { get; set; }
-
- [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string MediaTypes { get; set; }
-
- public string[] GetMediaTypes()
- {
- return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetIncludeItemTypes()
- {
- return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-
- [Route("/Items/Filters2", "GET", Summary = "Gets branding configuration")]
- public class GetQueryFilters : IReturn<QueryFilters>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string IncludeItemTypes { get; set; }
-
- [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string MediaTypes { get; set; }
-
- public string[] GetMediaTypes()
- {
- return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetIncludeItemTypes()
- {
- return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public bool? IsAiring { get; set; }
-
- public bool? IsMovie { get; set; }
-
- public bool? IsSports { get; set; }
-
- public bool? IsKids { get; set; }
-
- public bool? IsNews { get; set; }
-
- public bool? IsSeries { get; set; }
-
- public bool? Recursive { get; set; }
- }
-
- [Authenticated]
- public class FilterService : BaseApiService
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IUserManager _userManager;
-
- public FilterService(
- ILogger<FilterService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ILibraryManager libraryManager,
- IUserManager userManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _libraryManager = libraryManager;
- _userManager = userManager;
- }
-
- public object Get(GetQueryFilters request)
- {
- var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
- {
- parentItem = null;
- }
-
- var filters = new QueryFilters();
-
- var genreQuery = new InternalItemsQuery(user)
- {
- IncludeItemTypes = request.GetIncludeItemTypes(),
- DtoOptions = new Controller.Dto.DtoOptions
- {
- Fields = Array.Empty<ItemFields>(),
- EnableImages = false,
- EnableUserData = false
- },
- IsAiring = request.IsAiring,
- IsMovie = request.IsMovie,
- IsSports = request.IsSports,
- IsKids = request.IsKids,
- IsNews = request.IsNews,
- IsSeries = request.IsSeries
- };
-
- // Non recursive not yet supported for library folders
- if ((request.Recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
- {
- genreQuery.AncestorIds = parentItem == null ? Array.Empty<Guid>() : new[] { parentItem.Id };
- }
- else
- {
- genreQuery.Parent = parentItem;
- }
-
- if (string.Equals(request.IncludeItemTypes, "MusicAlbum", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "MusicVideo", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "MusicArtist", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "Audio", StringComparison.OrdinalIgnoreCase))
- {
- filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
- {
- Name = i.Item1.Name,
- Id = i.Item1.Id
- }).ToArray();
- }
- else
- {
- filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
- {
- Name = i.Item1.Name,
- Id = i.Item1.Id
- }).ToArray();
- }
-
- return ToOptimizedResult(filters);
- }
-
- public object Get(GetQueryFiltersLegacy request)
- {
- var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
- {
- parentItem = null;
- }
-
- var item = string.IsNullOrEmpty(request.ParentId) ?
- user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder() :
- parentItem;
-
- var result = ((Folder)item).GetItemList(GetItemsQuery(request, user));
-
- var filters = GetFilters(result);
-
- return ToOptimizedResult(filters);
- }
-
- private QueryFiltersLegacy GetFilters(IReadOnlyCollection<BaseItem> items)
- {
- var result = new QueryFiltersLegacy();
-
- result.Years = items.Select(i => i.ProductionYear ?? -1)
- .Where(i => i > 0)
- .Distinct()
- .OrderBy(i => i)
- .ToArray();
-
- result.Genres = items.SelectMany(i => i.Genres)
- .DistinctNames()
- .OrderBy(i => i)
- .ToArray();
-
- result.Tags = items
- .SelectMany(i => i.Tags)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .OrderBy(i => i)
- .ToArray();
-
- result.OfficialRatings = items
- .Select(i => i.OfficialRating)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .OrderBy(i => i)
- .ToArray();
-
- return result;
- }
-
- private InternalItemsQuery GetItemsQuery(GetQueryFiltersLegacy request, User user)
- {
- var query = new InternalItemsQuery
- {
- User = user,
- MediaTypes = request.GetMediaTypes(),
- IncludeItemTypes = request.GetIncludeItemTypes(),
- Recursive = true,
- EnableTotalRecordCount = false,
- DtoOptions = new Controller.Dto.DtoOptions
- {
- Fields = new[] { ItemFields.Genres, ItemFields.Tags },
- EnableImages = false,
- EnableUserData = false
- }
- };
-
- return query;
- }
- }
-}
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
deleted file mode 100644
index 2d405ac3d..000000000
--- 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
-{
- /// <summary>
- /// Class GetGeneralImage.
- /// </summary>
- [Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")]
- public class GetGeneralImage
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Type", Description = "Image Type (primary, backdrop, logo, etc).", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Type { get; set; }
- }
-
- /// <summary>
- /// Class GetRatingImage.
- /// </summary>
- [Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")]
- public class GetRatingImage
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the theme.
- /// </summary>
- /// <value>The theme.</value>
- [ApiMember(Name = "Theme", Description = "The theme to get the image from", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Theme { get; set; }
- }
-
- /// <summary>
- /// Class GetMediaInfoImage.
- /// </summary>
- [Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")]
- public class GetMediaInfoImage
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The name of the image", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the theme.
- /// </summary>
- /// <value>The theme.</value>
- [ApiMember(Name = "Theme", Description = "The theme to get the image from", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Theme { get; set; }
- }
-
- [Route("/Images/MediaInfo", "GET", Summary = "Gets all media info image by name")]
- [Authenticated]
- public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
- {
- }
-
- [Route("/Images/Ratings", "GET", Summary = "Gets all rating images by name")]
- [Authenticated]
- public class GetRatingImages : IReturn<List<ImageByNameInfo>>
- {
- }
-
- [Route("/Images/General", "GET", Summary = "Gets all general images by name")]
- [Authenticated]
- public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
- {
- }
-
- /// <summary>
- /// Class ImageByNameService.
- /// </summary>
- public class ImageByNameService : BaseApiService
- {
- /// <summary>
- /// The _app paths.
- /// </summary>
- private readonly IServerApplicationPaths _appPaths;
-
- private readonly IFileSystem _fileSystem;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ImageByNameService" /> class.
- /// </summary>
- public ImageByNameService(
- ILogger<ImageByNameService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory resultFactory,
- IFileSystem fileSystem)
- : base(logger, serverConfigurationManager, resultFactory)
- {
- _appPaths = serverConfigurationManager.ApplicationPaths;
- _fileSystem = fileSystem;
- }
-
- public object Get(GetMediaInfoImages request)
- {
- return ToOptimizedResult(GetImageList(_appPaths.MediaInfoImagesPath, true));
- }
-
- public object Get(GetRatingImages request)
- {
- return ToOptimizedResult(GetImageList(_appPaths.RatingsPath, true));
- }
-
- public object Get(GetGeneralImages request)
- {
- return ToOptimizedResult(GetImageList(_appPaths.GeneralPath, false));
- }
-
- private List<ImageByNameInfo> GetImageList(string path, bool supportsThemes)
- {
- try
- {
- return _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, true)
- .Select(i => new ImageByNameInfo
- {
- Name = _fileSystem.GetFileNameWithoutExtension(i),
- FileLength = i.Length,
-
- // For themeable images, use the Theme property
- // For general images, the same object structure is fine,
- // but it's not owned by a theme, so call it Context
- Theme = supportsThemes ? GetThemeName(i.FullName, path) : null,
- Context = supportsThemes ? null : GetThemeName(i.FullName, path),
-
- Format = i.Extension.ToLowerInvariant().TrimStart('.')
- })
- .OrderBy(i => i.Name)
- .ToList();
- }
- catch (IOException)
- {
- return new List<ImageByNameInfo>();
- }
- }
-
- private string GetThemeName(string path, string rootImagePath)
- {
- var parentName = Path.GetDirectoryName(path);
-
- if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- parentName = Path.GetFileName(parentName);
-
- return string.Equals(parentName, "all", StringComparison.OrdinalIgnoreCase) ?
- null :
- parentName;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public Task<object> Get(GetGeneralImage request)
- {
- var filename = string.Equals(request.Type, "primary", StringComparison.OrdinalIgnoreCase)
- ? "folder"
- : request.Type;
-
- var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList();
-
- var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault();
-
- return ResultFactory.GetStaticFileResult(Request, path);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetRatingImage request)
- {
- var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme);
-
- if (Directory.Exists(themeFolder))
- {
- var path = BaseItem.SupportedImageExtensions
- .Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
-
- if (!string.IsNullOrEmpty(path))
- {
- return ResultFactory.GetStaticFileResult(Request, path);
- }
- }
-
- var allFolder = Path.Combine(_appPaths.RatingsPath, "all");
-
- if (Directory.Exists(allFolder))
- {
- // Avoid implicitly captured closure
- var currentRequest = request;
-
- var path = BaseItem.SupportedImageExtensions
- .Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
-
- if (!string.IsNullOrEmpty(path))
- {
- return ResultFactory.GetStaticFileResult(Request, path);
- }
- }
-
- throw new ResourceNotFoundException("MediaInfo image not found: " + request.Name);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public Task<object> Get(GetMediaInfoImage request)
- {
- var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme);
-
- if (Directory.Exists(themeFolder))
- {
- var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
-
- if (!string.IsNullOrEmpty(path))
- {
- return ResultFactory.GetStaticFileResult(Request, path);
- }
- }
-
- var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all");
-
- if (Directory.Exists(allFolder))
- {
- // Avoid implicitly captured closure
- var currentRequest = request;
-
- var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
-
- if (!string.IsNullOrEmpty(path))
- {
- return ResultFactory.GetStaticFileResult(Request, path);
- }
- }
-
- throw new ResourceNotFoundException("MediaInfo image not found: " + request.Name);
- }
- }
-}
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
deleted file mode 100644
index 86464b4b9..000000000
--- 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<RemoteImageResult>
- {
- [ApiMember(Name = "Type", Description = "The image type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public ImageType? Type { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "ProviderName", Description = "Optional. The image provider to use", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ProviderName { get; set; }
-
- [ApiMember(Name = "IncludeAllLanguages", Description = "Optional.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludeAllLanguages { get; set; }
- }
-
- [Route("/Items/{Id}/RemoteImages", "GET", Summary = "Gets available remote images for an item")]
- [Authenticated]
- public class GetRemoteImages : BaseRemoteImageRequest
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Items/{Id}/RemoteImages/Providers", "GET", Summary = "Gets available remote image providers for an item")]
- [Authenticated]
- public class GetRemoteImageProviders : IReturn<List<ImageProviderInfo>>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- public class BaseDownloadRemoteImage : IReturnVoid
- {
- [ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public ImageType Type { get; set; }
-
- [ApiMember(Name = "ProviderName", Description = "The image provider", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string ProviderName { get; set; }
-
- [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string ImageUrl { get; set; }
- }
-
- [Route("/Items/{Id}/RemoteImages/Download", "POST", Summary = "Downloads a remote image for an item")]
- [Authenticated(Roles = "Admin")]
- public class DownloadRemoteImage : BaseDownloadRemoteImage
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Images/Remote", "GET", Summary = "Gets a remote image")]
- public class GetRemoteImage
- {
- [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ImageUrl { get; set; }
- }
-
- public class RemoteImageService : BaseApiService
- {
- private readonly IProviderManager _providerManager;
-
- private readonly IServerApplicationPaths _appPaths;
- private readonly IHttpClient _httpClient;
- private readonly IFileSystem _fileSystem;
-
- private readonly ILibraryManager _libraryManager;
-
- public RemoteImageService(
- ILogger<RemoteImageService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IProviderManager providerManager,
- IServerApplicationPaths appPaths,
- IHttpClient httpClient,
- IFileSystem fileSystem,
- ILibraryManager libraryManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _providerManager = providerManager;
- _appPaths = appPaths;
- _httpClient = httpClient;
- _fileSystem = fileSystem;
- _libraryManager = libraryManager;
- }
-
- public object Get(GetRemoteImageProviders request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var result = GetImageProviders(item);
-
- return ToOptimizedResult(result);
- }
-
- private List<ImageProviderInfo> GetImageProviders(BaseItem item)
- {
- return _providerManager.GetRemoteImageProviderInfo(item).ToList();
- }
-
- public async Task<object> Get(GetRemoteImages request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery(request.ProviderName)
- {
- IncludeAllLanguages = request.IncludeAllLanguages,
- IncludeDisabledProviders = true,
- ImageType = request.Type
- }, CancellationToken.None).ConfigureAwait(false);
-
- var imagesList = images.ToArray();
-
- var allProviders = _providerManager.GetRemoteImageProviderInfo(item);
-
- if (request.Type.HasValue)
- {
- allProviders = allProviders.Where(i => i.SupportedImages.Contains(request.Type.Value));
- }
-
- var result = new RemoteImageResult
- {
- TotalRecordCount = imagesList.Length,
- Providers = allProviders.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToArray()
- };
-
- if (request.StartIndex.HasValue)
- {
- imagesList = imagesList.Skip(request.StartIndex.Value)
- .ToArray();
- }
-
- if (request.Limit.HasValue)
- {
- imagesList = imagesList.Take(request.Limit.Value)
- .ToArray();
- }
-
- result.Images = imagesList;
-
- return result;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(DownloadRemoteImage request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- return DownloadRemoteImage(item, request);
- }
-
- /// <summary>
- /// Downloads the remote image.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="request">The request.</param>
- /// <returns>Task.</returns>
- private async Task DownloadRemoteImage(BaseItem item, BaseDownloadRemoteImage request)
- {
- await _providerManager.SaveImage(item, request.ImageUrl, request.Type, null, CancellationToken.None).ConfigureAwait(false);
-
- item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Get(GetRemoteImage request)
- {
- var urlHash = request.ImageUrl.GetMD5();
- var pointerCachePath = GetFullCachePath(urlHash.ToString());
-
- string contentPath;
-
- try
- {
- contentPath = File.ReadAllText(pointerCachePath);
-
- if (File.Exists(contentPath))
- {
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
- }
- catch (FileNotFoundException)
- {
- // Means the file isn't cached yet
- }
- catch (IOException)
- {
- // Means the file isn't cached yet
- }
-
- await DownloadImage(request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
-
- // Read the pointer file again
- contentPath = File.ReadAllText(pointerCachePath);
-
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Downloads the image.
- /// </summary>
- /// <param name="url">The URL.</param>
- /// <param name="urlHash">The URL hash.</param>
- /// <param name="pointerCachePath">The pointer cache path.</param>
- /// <returns>Task.</returns>
- private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath)
- {
- using var result = await _httpClient.GetResponse(new HttpRequestOptions
- {
- Url = url,
- BufferContent = false
- }).ConfigureAwait(false);
- var ext = result.ContentType.Split('/')[^1];
-
- var fullCachePath = GetFullCachePath(urlHash + "." + ext);
-
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
- var stream = result.Content;
- await using (stream.ConfigureAwait(false))
- {
- var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
- await using (filestream.ConfigureAwait(false))
- {
- await stream.CopyToAsync(filestream).ConfigureAwait(false);
- }
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
- File.WriteAllText(pointerCachePath, fullCachePath);
- }
-
- /// <summary>
- /// Gets the full cache path.
- /// </summary>
- /// <param name="filename">The filename.</param>
- /// <returns>System.String.</returns>
- private string GetFullCachePath(string filename)
- {
- return Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
- }
- }
-}
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
deleted file mode 100644
index 862411209..000000000
--- 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<List<ExternalIdInfo>>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
- }
-
- [Route("/Items/RemoteSearch/Movie", "POST")]
- [Authenticated]
- public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Trailer", "POST")]
- [Authenticated]
- public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicVideo", "POST")]
- [Authenticated]
- public class GetMusicVideoRemoteSearchResults : RemoteSearchQuery<MusicVideoInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Series", "POST")]
- [Authenticated]
- public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/BoxSet", "POST")]
- [Authenticated]
- public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicArtist", "POST")]
- [Authenticated]
- public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicAlbum", "POST")]
- [Authenticated]
- public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Person", "POST")]
- [Authenticated(Roles = "Admin")]
- public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Book", "POST")]
- [Authenticated]
- public class GetBookRemoteSearchResults : RemoteSearchQuery<BookInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Image", "GET", Summary = "Gets a remote image")]
- public class GetRemoteSearchImage
- {
- [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ImageUrl { get; set; }
-
- [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ProviderName { get; set; }
- }
-
- [Route("/Items/RemoteSearch/Apply/{Id}", "POST", Summary = "Applies search criteria to an item and refreshes metadata")]
- [Authenticated(Roles = "Admin")]
- public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "ReplaceAllImages", Description = "Whether or not to replace all images", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool ReplaceAllImages { get; set; }
-
- public ApplySearchCriteria()
- {
- ReplaceAllImages = true;
- }
- }
-
- public class ItemLookupService : BaseApiService
- {
- private readonly IProviderManager _providerManager;
- private readonly IServerApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
- private readonly ILibraryManager _libraryManager;
- private readonly IJsonSerializer _json;
-
- public ItemLookupService(
- ILogger<ItemLookupService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IProviderManager providerManager,
- IFileSystem fileSystem,
- ILibraryManager libraryManager,
- IJsonSerializer json)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _providerManager = providerManager;
- _appPaths = serverConfigurationManager.ApplicationPaths;
- _fileSystem = fileSystem;
- _libraryManager = libraryManager;
- _json = json;
- }
-
- public object Get(GetExternalIdInfos request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var infos = _providerManager.GetExternalIdInfos(item).ToList();
-
- return ToOptimizedResult(infos);
- }
-
- public async Task<object> Post(GetTrailerRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetBookRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Book, BookInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMovieRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetSeriesRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetBoxSetRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicVideoRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicVideo, MusicVideoInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetPersonRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicAlbumRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicArtistRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public Task<object> Get(GetRemoteSearchImage request)
- {
- return GetRemoteImage(request);
- }
-
- public Task Post(ApplySearchCriteria request)
- {
- var item = _libraryManager.GetItemById(new Guid(request.Id));
-
- // foreach (var key in request.ProviderIds)
- //{
- // var value = key.Value;
-
- // if (!string.IsNullOrWhiteSpace(value))
- // {
- // item.SetProviderId(key.Key, value);
- // }
- //}
- Logger.LogInformation("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds));
-
- // Since the refresh process won't erase provider Ids, we need to set this explicitly now.
- item.ProviderIds = request.ProviderIds;
- // item.ProductionYear = request.ProductionYear;
- // item.Name = request.Name;
-
- return _providerManager.RefreshFullItem(
- item,
- new MetadataRefreshOptions(new DirectoryService(_fileSystem))
- {
- MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
- ImageRefreshMode = MetadataRefreshMode.FullRefresh,
- ReplaceAllMetadata = true,
- ReplaceAllImages = request.ReplaceAllImages,
- SearchResult = request
- },
- CancellationToken.None);
- }
-
- /// <summary>
- /// Gets the remote image.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{System.Object}.</returns>
- private async Task<object> GetRemoteImage(GetRemoteSearchImage request)
- {
- var urlHash = request.ImageUrl.GetMD5();
- var pointerCachePath = GetFullCachePath(urlHash.ToString());
-
- string contentPath;
-
- try
- {
- contentPath = File.ReadAllText(pointerCachePath);
-
- if (File.Exists(contentPath))
- {
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
- }
- catch (FileNotFoundException)
- {
- // Means the file isn't cached yet
- }
- catch (IOException)
- {
- // Means the file isn't cached yet
- }
-
- await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
-
- // Read the pointer file again
- contentPath = File.ReadAllText(pointerCachePath);
-
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Downloads the image.
- /// </summary>
- /// <param name="providerName">Name of the provider.</param>
- /// <param name="url">The URL.</param>
- /// <param name="urlHash">The URL hash.</param>
- /// <param name="pointerCachePath">The pointer cache path.</param>
- /// <returns>Task.</returns>
- private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath)
- {
- var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
-
- var ext = result.ContentType.Split('/')[^1];
-
- var fullCachePath = GetFullCachePath(urlHash + "." + ext);
-
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
- var stream = result.Content;
-
- await using (stream.ConfigureAwait(false))
- {
- var fileStream = new FileStream(
- fullCachePath,
- FileMode.Create,
- FileAccess.Write,
- FileShare.Read,
- IODefaults.FileStreamBufferSize,
- true);
- await using (fileStream.ConfigureAwait(false))
- {
- await stream.CopyToAsync(fileStream).ConfigureAwait(false);
- }
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
- File.WriteAllText(pointerCachePath, fullCachePath);
- }
-
- /// <summary>
- /// Gets the full cache path.
- /// </summary>
- /// <param name="filename">The filename.</param>
- /// <returns>System.String.</returns>
- private string GetFullCachePath(string filename)
- => Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
- }
-}
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
deleted file mode 100644
index 6555864dc..000000000
--- 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
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetCriticReviews.
- /// </summary>
- [Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")]
- [Authenticated]
- public class GetCriticReviews : IReturn<QueryResult<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
- }
-
- /// <summary>
- /// Class GetThemeSongs.
- /// </summary>
- [Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")]
- [Authenticated]
- public class GetThemeSongs : IReturn<ThemeMediaResult>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool InheritFromParent { get; set; }
- }
-
- /// <summary>
- /// Class GetThemeVideos.
- /// </summary>
- [Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")]
- [Authenticated]
- public class GetThemeVideos : IReturn<ThemeMediaResult>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool InheritFromParent { get; set; }
- }
-
- /// <summary>
- /// Class GetThemeVideos.
- /// </summary>
- [Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")]
- [Authenticated]
- public class GetThemeMedia : IReturn<AllThemeMediaResult>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "InheritFromParent", Description = "Determines whether or not parent items should be searched for theme media.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool InheritFromParent { get; set; }
- }
-
- [Route("/Library/Refresh", "POST", Summary = "Starts a library scan")]
- [Authenticated(Roles = "Admin")]
- public class RefreshLibrary : IReturnVoid
- {
- }
-
- [Route("/Items/{Id}", "DELETE", Summary = "Deletes an item from the library and file system")]
- [Authenticated]
- public class DeleteItem : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Items", "DELETE", Summary = "Deletes an item from the library and file system")]
- [Authenticated]
- public class DeleteItems : IReturnVoid
- {
- [ApiMember(Name = "Ids", Description = "Ids", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Ids { get; set; }
- }
-
- [Route("/Items/Counts", "GET")]
- [Authenticated]
- public class GetItemCounts : IReturn<ItemCounts>
- {
- [ApiMember(Name = "UserId", Description = "Optional. Get counts from a specific user's library.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "IsFavorite", Description = "Optional. Get counts of favorite items", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsFavorite { get; set; }
- }
-
- [Route("/Items/{Id}/Ancestors", "GET", Summary = "Gets all parents of an item")]
- [Authenticated]
- public class GetAncestors : IReturn<BaseItemDto[]>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetPhyscialPaths.
- /// </summary>
- [Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")]
- [Authenticated(Roles = "Admin")]
- public class GetPhyscialPaths : IReturn<List<string>>
- {
- }
-
- [Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
- [Authenticated]
- public class GetMediaFolders : IReturn<QueryResult<BaseItemDto>>
- {
- [ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? IsHidden { get; set; }
- }
-
- [Route("/Library/Series/Added", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
- [Route("/Library/Series/Updated", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
- [Authenticated]
- public class PostUpdatedSeries : IReturnVoid
- {
- [ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string TvdbId { get; set; }
- }
-
- [Route("/Library/Movies/Added", "POST", Summary = "Reports that new movies have been added by an external source")]
- [Route("/Library/Movies/Updated", "POST", Summary = "Reports that new movies have been added by an external source")]
- [Authenticated]
- public class PostUpdatedMovies : IReturnVoid
- {
- [ApiMember(Name = "TmdbId", Description = "Tmdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string TmdbId { get; set; }
- [ApiMember(Name = "ImdbId", Description = "Imdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string ImdbId { get; set; }
- }
-
- public class MediaUpdateInfo
- {
- public string Path { get; set; }
-
- // Created, Modified, Deleted
- public string UpdateType { get; set; }
- }
-
- [Route("/Library/Media/Updated", "POST", Summary = "Reports that new movies have been added by an external source")]
- [Authenticated]
- public class PostUpdatedMedia : IReturnVoid
- {
- [ApiMember(Name = "Updates", Description = "A list of updated media paths", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public List<MediaUpdateInfo> Updates { get; set; }
- }
-
- [Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
- [Authenticated(Roles = "download")]
- public class GetDownload
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Artists/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
- [Route("/Items/{Id}/Similar", "GET", Summary = "Gets similar items")]
- [Route("/Albums/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
- [Route("/Shows/{Id}/Similar", "GET", Summary = "Finds tv shows similar to a given one.")]
- [Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
- [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
- [Authenticated]
- public class GetSimilarItems : BaseGetSimilarItemsFromItem
- {
- }
-
- [Route("/Libraries/AvailableOptions", "GET")]
- [Authenticated(AllowBeforeStartupWizard = true)]
- public class GetLibraryOptionsInfo : IReturn<LibraryOptionsResult>
- {
- public string LibraryContentType { get; set; }
-
- public bool IsNewLibrary { get; set; }
- }
-
- public class LibraryOptionInfo
- {
- public string Name { get; set; }
-
- public bool DefaultEnabled { get; set; }
- }
-
- public class LibraryOptionsResult
- {
- public LibraryOptionInfo[] MetadataSavers { get; set; }
-
- public LibraryOptionInfo[] MetadataReaders { get; set; }
-
- public LibraryOptionInfo[] SubtitleFetchers { get; set; }
-
- public LibraryTypeOptions[] TypeOptions { get; set; }
- }
-
- public class LibraryTypeOptions
- {
- public string Type { get; set; }
-
- public LibraryOptionInfo[] MetadataFetchers { get; set; }
-
- public LibraryOptionInfo[] ImageFetchers { get; set; }
-
- public ImageType[] SupportedImageTypes { get; set; }
-
- public ImageOption[] DefaultImageOptions { get; set; }
- }
-
- /// <summary>
- /// Class LibraryService.
- /// </summary>
- public class LibraryService : BaseApiService
- {
- private readonly IProviderManager _providerManager;
- private readonly ILibraryManager _libraryManager;
- private readonly IUserManager _userManager;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
- private readonly IActivityManager _activityManager;
- private readonly ILocalizationManager _localization;
- private readonly ILibraryMonitor _libraryMonitor;
-
- private readonly ILogger<MoviesService> _moviesServiceLogger;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LibraryService" /> class.
- /// </summary>
- public LibraryService(
- ILogger<LibraryService> logger,
- ILogger<MoviesService> moviesServiceLogger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IProviderManager providerManager,
- ILibraryManager libraryManager,
- IUserManager userManager,
- IDtoService dtoService,
- IAuthorizationContext authContext,
- IActivityManager activityManager,
- ILocalizationManager localization,
- ILibraryMonitor libraryMonitor)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _providerManager = providerManager;
- _libraryManager = libraryManager;
- _userManager = userManager;
- _dtoService = dtoService;
- _authContext = authContext;
- _activityManager = activityManager;
- _localization = localization;
- _libraryMonitor = libraryMonitor;
- _moviesServiceLogger = moviesServiceLogger;
- }
-
- // Content Types available for each Library
- private string[] GetRepresentativeItemTypes(string contentType)
- {
- return contentType switch
- {
- CollectionType.BoxSets => new[] {"BoxSet"},
- CollectionType.Playlists => new[] {"Playlist"},
- CollectionType.Movies => new[] {"Movie"},
- CollectionType.TvShows => new[] {"Series", "Season", "Episode"},
- CollectionType.Books => new[] {"Book"},
- CollectionType.Music => new[] {"MusicArtist", "MusicAlbum", "Audio", "MusicVideo"},
- CollectionType.HomeVideos => new[] {"Video", "Photo"},
- CollectionType.Photos => new[] {"Video", "Photo"},
- CollectionType.MusicVideos => new[] {"MusicVideo"},
- _ => new[] {"Series", "Season", "Episode", "Movie"}
- };
- }
-
- private bool IsSaverEnabledByDefault(string name, string[] itemTypes, bool isNewLibrary)
- {
- if (isNewLibrary)
- {
- return false;
- }
-
- var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
- .Where(i => itemTypes.Contains(i.ItemType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
- .ToArray();
-
- if (metadataOptions.Length == 0)
- {
- return true;
- }
-
- return metadataOptions.Any(i => !i.DisabledMetadataSavers.Contains(name, StringComparer.OrdinalIgnoreCase));
- }
-
- private bool IsMetadataFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
- {
- if (isNewLibrary)
- {
- if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
- {
- return !(string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
- || string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
- || string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase));
- }
-
- return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
- }
-
- var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .ToArray();
-
- return metadataOptions.Length == 0
- || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase));
- }
-
- private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
- {
- if (isNewLibrary)
- {
- if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
- {
- return !string.Equals(type, "Series", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase);
- }
-
- return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "Screen Grabber", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "Image Extractor", StringComparison.OrdinalIgnoreCase);
- }
-
- var metadataOptions = ServerConfigurationManager.Configuration.MetadataOptions
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .ToArray();
-
- if (metadataOptions.Length == 0)
- {
- return true;
- }
-
- return metadataOptions.Any(i => !i.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase));
- }
-
- public object Get(GetLibraryOptionsInfo request)
- {
- var result = new LibraryOptionsResult();
-
- var types = GetRepresentativeItemTypes(request.LibraryContentType);
- var isNewLibrary = request.IsNewLibrary;
- var typesList = types.ToList();
-
- var plugins = _providerManager.GetAllMetadataPlugins()
- .Where(i => types.Contains(i.ItemType, StringComparer.OrdinalIgnoreCase))
- .OrderBy(i => typesList.IndexOf(i.ItemType))
- .ToList();
-
- result.MetadataSavers = plugins
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataSaver))
- .Select(i => new LibraryOptionInfo
- {
- Name = i.Name,
- DefaultEnabled = IsSaverEnabledByDefault(i.Name, types, isNewLibrary)
- })
- .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .Select(x => x.First())
- .ToArray();
-
- result.MetadataReaders = plugins
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.LocalMetadataProvider))
- .Select(i => new LibraryOptionInfo
- {
- Name = i.Name,
- DefaultEnabled = true
- })
- .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .Select(x => x.First())
- .ToArray();
-
- result.SubtitleFetchers = plugins
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.SubtitleFetcher))
- .Select(i => new LibraryOptionInfo
- {
- Name = i.Name,
- DefaultEnabled = true
- })
- .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .Select(x => x.First())
- .ToArray();
-
- var typeOptions = new List<LibraryTypeOptions>();
-
- foreach (var type in types)
- {
- TypeOptions.DefaultImageOptions.TryGetValue(type, out var defaultImageOptions);
-
- typeOptions.Add(new LibraryTypeOptions
- {
- Type = type,
-
- MetadataFetchers = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataFetcher))
- .Select(i => new LibraryOptionInfo
- {
- Name = i.Name,
- DefaultEnabled = IsMetadataFetcherEnabledByDefault(i.Name, type, isNewLibrary)
- })
- .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .Select(x => x.First())
- .ToArray(),
-
- ImageFetchers = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.ImageFetcher))
- .Select(i => new LibraryOptionInfo
- {
- Name = i.Name,
- DefaultEnabled = IsImageFetcherEnabledByDefault(i.Name, type, isNewLibrary)
- })
- .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .Select(x => x.First())
- .ToArray(),
-
- SupportedImageTypes = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.SupportedImageTypes ?? Array.Empty<ImageType>())
- .Distinct()
- .ToArray(),
-
- DefaultImageOptions = defaultImageOptions ?? Array.Empty<ImageOption>()
- });
- }
-
- result.TypeOptions = typeOptions.ToArray();
-
- return result;
- }
-
- public object Get(GetSimilarItems request)
- {
- var item = string.IsNullOrEmpty(request.Id) ?
- (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
- _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
- var program = item as IHasProgramAttributes;
-
- if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
- {
- return new MoviesService(
- _moviesServiceLogger,
- ServerConfigurationManager,
- ResultFactory,
- _userManager,
- _libraryManager,
- _dtoService,
- _authContext)
- {
- Request = Request,
- }.GetSimilarItemsResult(request);
- }
-
- if (program != null && program.IsSeries)
- {
- return GetSimilarItemsResult(request, new[] { typeof(Series).Name });
- }
-
- if (item is Episode || (item is IItemByName && !(item is MusicArtist)))
- {
- return new QueryResult<BaseItemDto>();
- }
-
- return GetSimilarItemsResult(request, new[] { item.GetType().Name });
- }
-
- private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, string[] includeItemTypes)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var item = string.IsNullOrEmpty(request.Id) ?
- (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
- _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var query = new InternalItemsQuery(user)
- {
- Limit = request.Limit,
- IncludeItemTypes = includeItemTypes,
- SimilarTo = item,
- DtoOptions = dtoOptions,
- EnableTotalRecordCount = false
- };
-
- // ExcludeArtistIds
- if (!string.IsNullOrEmpty(request.ExcludeArtistIds))
- {
- query.ExcludeArtistIds = GetGuids(request.ExcludeArtistIds);
- }
-
- List<BaseItem> itemsResult;
-
- if (item is MusicArtist)
- {
- query.IncludeItemTypes = Array.Empty<string>();
-
- itemsResult = _libraryManager.GetArtists(query).Items.Select(i => i.Item1).ToList();
- }
- else
- {
- itemsResult = _libraryManager.GetItemList(query);
- }
-
- var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnList,
- TotalRecordCount = itemsResult.Count
- };
-
- return result;
- }
-
- public object Get(GetMediaFolders request)
- {
- var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
-
- if (request.IsHidden.HasValue)
- {
- var val = request.IsHidden.Value;
-
- items = items.Where(i => i.IsHidden == val).ToList();
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = items.Count,
-
- Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)).ToArray()
- };
-
- return result;
- }
-
- public void Post(PostUpdatedSeries request)
- {
- var series = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Series).Name },
- DtoOptions = new DtoOptions(false)
- {
- EnableImages = false
- }
- }).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProvider.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
-
- foreach (var item in series)
- {
- _libraryMonitor.ReportFileSystemChanged(item.Path);
- }
- }
-
- public void Post(PostUpdatedMedia request)
- {
- if (request.Updates != null)
- {
- foreach (var item in request.Updates)
- {
- _libraryMonitor.ReportFileSystemChanged(item.Path);
- }
- }
- }
-
- public void Post(PostUpdatedMovies request)
- {
- var movies = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Movie).Name },
- DtoOptions = new DtoOptions(false)
- {
- EnableImages = false
- }
- });
-
- if (!string.IsNullOrWhiteSpace(request.ImdbId))
- {
- movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProvider.Imdb), StringComparison.OrdinalIgnoreCase)).ToList();
- }
- else if (!string.IsNullOrWhiteSpace(request.TmdbId))
- {
- movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProvider.Tmdb), StringComparison.OrdinalIgnoreCase)).ToList();
- }
- else
- {
- movies = new List<BaseItem>();
- }
-
- foreach (var item in movies)
- {
- _libraryMonitor.ReportFileSystemChanged(item.Path);
- }
- }
-
- public Task<object> Get(GetDownload request)
- {
- var item = _libraryManager.GetItemById(request.Id);
- var auth = _authContext.GetAuthorizationInfo(Request);
-
- var user = auth.User;
-
- if (user != null)
- {
- if (!item.CanDownload(user))
- {
- throw new ArgumentException("Item does not support downloading");
- }
- }
- else
- {
- if (!item.CanDownload())
- {
- throw new ArgumentException("Item does not support downloading");
- }
- }
-
- var headers = new Dictionary<string, string>();
-
- if (user != null)
- {
- LogDownload(item, user, auth);
- }
-
- var path = item.Path;
-
- // Quotes are valid in linux. They'll possibly cause issues here
- var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty);
- if (!string.IsNullOrWhiteSpace(filename))
- {
- // Kestrel doesn't support non-ASCII characters in headers
- if (Regex.IsMatch(filename, @"[^\p{IsBasicLatin}]"))
- {
- // Manually encoding non-ASCII characters, following https://tools.ietf.org/html/rfc5987#section-3.2.2
- headers[HeaderNames.ContentDisposition] = "attachment; filename*=UTF-8''" + WebUtility.UrlEncode(filename);
- }
- else
- {
- headers[HeaderNames.ContentDisposition] = "attachment; filename=\"" + filename + "\"";
- }
- }
-
- return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
- {
- Path = path,
- ResponseHeaders = headers
- });
- }
-
- private void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
- {
- try
- {
- _activityManager.Create(new ActivityLog(
- string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name),
- "UserDownloadingContent",
- auth.UserId)
- {
- ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
- });
- }
- catch
- {
- // Logged at lower levels
- }
- }
-
- public Task<object> Get(GetFile request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- return ResultFactory.GetStaticFileResult(Request, item.Path);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPhyscialPaths request)
- {
- var result = _libraryManager.RootFolder.Children
- .SelectMany(c => c.PhysicalLocations)
- .ToList();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetAncestors request)
- {
- var result = GetAncestors(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the ancestors.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto[]}.</returns>
- public List<BaseItemDto> GetAncestors(GetAncestors request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var baseItemDtos = new List<BaseItemDto>();
-
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- BaseItem parent = item.GetParent();
-
- while (parent != null)
- {
- if (user != null)
- {
- parent = TranslateParentItem(parent, user);
- }
-
- baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
-
- parent = parent.GetParent();
- }
-
- return baseItemDtos;
- }
-
- private BaseItem TranslateParentItem(BaseItem item, User user)
- {
- return item.GetParent() is AggregateFolder
- ? _libraryManager.GetUserRootFolder().GetChildren(user, true)
- .FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path))
- : item;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetCriticReviews request)
- {
- return new QueryResult<BaseItemDto>();
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetItemCounts request)
- {
- var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
- var counts = new ItemCounts
- {
- AlbumCount = GetCount(typeof(MusicAlbum), user, request),
- EpisodeCount = GetCount(typeof(Episode), user, request),
- MovieCount = GetCount(typeof(Movie), user, request),
- SeriesCount = GetCount(typeof(Series), user, request),
- SongCount = GetCount(typeof(Audio), user, request),
- MusicVideoCount = GetCount(typeof(MusicVideo), user, request),
- BoxSetCount = GetCount(typeof(BoxSet), user, request),
- BookCount = GetCount(typeof(Book), user, request)
- };
-
- return ToOptimizedResult(counts);
- }
-
- private int GetCount(Type type, User user, GetItemCounts request)
- {
- var query = new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { type.Name },
- Limit = 0,
- Recursive = true,
- IsVirtualItem = false,
- IsFavorite = request.IsFavorite,
- DtoOptions = new DtoOptions(false)
- {
- EnableImages = false
- }
- };
-
- return _libraryManager.GetItemsResult(query).TotalRecordCount;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public async Task Post(RefreshLibrary request)
- {
- try
- {
- await _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, "Error refreshing library");
- }
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(DeleteItems request)
- {
- var ids = string.IsNullOrWhiteSpace(request.Ids)
- ? Array.Empty<string>()
- : request.Ids.Split(',');
-
- foreach (var i in ids)
- {
- var item = _libraryManager.GetItemById(i);
- var auth = _authContext.GetAuthorizationInfo(Request);
- var user = auth.User;
-
- if (!item.CanDelete(user))
- {
- if (ids.Length > 1)
- {
- throw new SecurityException("Unauthorized access");
- }
-
- continue;
- }
-
- _libraryManager.DeleteItem(item, new DeleteOptions
- {
- DeleteFileLocation = true
- }, true);
- }
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(DeleteItem request)
- {
- Delete(new DeleteItems
- {
- Ids = request.Id
- });
- }
-
- public object Get(GetThemeMedia request)
- {
- var themeSongs = GetThemeSongs(new GetThemeSongs
- {
- InheritFromParent = request.InheritFromParent,
- Id = request.Id,
- UserId = request.UserId
-
- });
-
- var themeVideos = GetThemeVideos(new GetThemeVideos
- {
- InheritFromParent = request.InheritFromParent,
- Id = request.Id,
- UserId = request.UserId
-
- });
-
- return ToOptimizedResult(new AllThemeMediaResult
- {
- ThemeSongsResult = themeSongs,
- ThemeVideosResult = themeVideos,
-
- SoundtrackSongsResult = new ThemeMediaResult()
- });
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetThemeSongs request)
- {
- var result = GetThemeSongs(request);
-
- return ToOptimizedResult(result);
- }
-
- private ThemeMediaResult GetThemeSongs(GetThemeSongs request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var item = string.IsNullOrEmpty(request.Id)
- ? (!request.UserId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
- : _libraryManager.GetItemById(request.Id);
-
- if (item == null)
- {
- throw new ResourceNotFoundException("Item not found.");
- }
-
- IEnumerable<BaseItem> themeItems;
-
- while (true)
- {
- themeItems = item.GetThemeSongs();
-
- if (themeItems.Any() || !request.InheritFromParent)
- {
- break;
- }
-
- var parent = item.GetParent();
- if (parent == null)
- {
- break;
- }
-
- item = parent;
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
- var items = themeItems
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
- .ToArray();
-
- return new ThemeMediaResult
- {
- Items = items,
- TotalRecordCount = items.Length,
- OwnerId = item.Id
- };
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetThemeVideos request)
- {
- return ToOptimizedResult(GetThemeVideos(request));
- }
-
- public ThemeMediaResult GetThemeVideos(GetThemeVideos request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var item = string.IsNullOrEmpty(request.Id)
- ? (!request.UserId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
- : _libraryManager.GetItemById(request.Id);
-
- if (item == null)
- {
- throw new ResourceNotFoundException("Item not found.");
- }
-
- IEnumerable<BaseItem> themeItems;
-
- while (true)
- {
- themeItems = item.GetThemeVideos();
-
- if (themeItems.Any() || !request.InheritFromParent)
- {
- break;
- }
-
- var parent = item.GetParent();
- if (parent == null)
- {
- break;
- }
-
- item = parent;
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = themeItems
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
- .ToArray();
-
- return new ThemeMediaResult
- {
- Items = items,
- TotalRecordCount = items.Length,
- OwnerId = item.Id
- };
- }
- }
-}
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
deleted file mode 100644
index b69550ed1..000000000
--- 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
-{
- /// <summary>
- /// Class GetDefaultVirtualFolders.
- /// </summary>
- [Route("/Library/VirtualFolders", "GET")]
- public class GetVirtualFolders : IReturn<List<VirtualFolderInfo>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- public string UserId { get; set; }
- }
-
- [Route("/Library/VirtualFolders", "POST")]
- public class AddVirtualFolder : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the type of the collection.
- /// </summary>
- /// <value>The type of the collection.</value>
- public string CollectionType { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [refresh library].
- /// </summary>
- /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
- public bool RefreshLibrary { get; set; }
-
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- public string[] Paths { get; set; }
-
- public LibraryOptions LibraryOptions { get; set; }
- }
-
- [Route("/Library/VirtualFolders", "DELETE")]
- public class RemoveVirtualFolder : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [refresh library].
- /// </summary>
- /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
- public bool RefreshLibrary { get; set; }
- }
-
- [Route("/Library/VirtualFolders/Name", "POST")]
- public class RenameVirtualFolder : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string NewName { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [refresh library].
- /// </summary>
- /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
- public bool RefreshLibrary { get; set; }
- }
-
- [Route("/Library/VirtualFolders/Paths", "POST")]
- public class AddMediaPath : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Path { get; set; }
-
- public MediaPathInfo PathInfo { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [refresh library].
- /// </summary>
- /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
- public bool RefreshLibrary { get; set; }
- }
-
- [Route("/Library/VirtualFolders/Paths/Update", "POST")]
- public class UpdateMediaPath : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- public MediaPathInfo PathInfo { get; set; }
- }
-
- [Route("/Library/VirtualFolders/Paths", "DELETE")]
- public class RemoveMediaPath : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Path { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [refresh library].
- /// </summary>
- /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
- public bool RefreshLibrary { get; set; }
- }
-
- [Route("/Library/VirtualFolders/LibraryOptions", "POST")]
- public class UpdateLibraryOptions : IReturnVoid
- {
- public string Id { get; set; }
-
- public LibraryOptions LibraryOptions { get; set; }
- }
-
- /// <summary>
- /// Class LibraryStructureService.
- /// </summary>
- [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
- public class LibraryStructureService : BaseApiService
- {
- /// <summary>
- /// The _app paths.
- /// </summary>
- private readonly IServerApplicationPaths _appPaths;
-
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly ILibraryMonitor _libraryMonitor;
-
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LibraryStructureService" /> class.
- /// </summary>
- public LibraryStructureService(
- ILogger<LibraryStructureService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ILibraryManager libraryManager,
- ILibraryMonitor libraryMonitor)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _appPaths = serverConfigurationManager.ApplicationPaths;
- _libraryManager = libraryManager;
- _libraryMonitor = libraryMonitor;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetVirtualFolders request)
- {
- var result = _libraryManager.GetVirtualFolders(true);
-
- return ToOptimizedResult(result);
- }
-
- public void Post(UpdateLibraryOptions request)
- {
- var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(request.Id);
-
- collectionFolder.UpdateLibraryOptions(request.LibraryOptions);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(AddVirtualFolder request)
- {
- var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
-
- if (request.Paths != null && request.Paths.Length > 0)
- {
- libraryOptions.PathInfos = request.Paths.Select(i => new MediaPathInfo { Path = i }).ToArray();
- }
-
- return _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, libraryOptions, request.RefreshLibrary);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(RenameVirtualFolder request)
- {
- if (string.IsNullOrWhiteSpace(request.Name))
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- if (string.IsNullOrWhiteSpace(request.NewName))
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- var rootFolderPath = _appPaths.DefaultUserViewsPath;
-
- var currentPath = Path.Combine(rootFolderPath, request.Name);
- var newPath = Path.Combine(rootFolderPath, request.NewName);
-
- if (!Directory.Exists(currentPath))
- {
- throw new FileNotFoundException("The media collection does not exist");
- }
-
- if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath))
- {
- throw new ArgumentException("Media library already exists at " + newPath + ".");
- }
-
- _libraryMonitor.Stop();
-
- try
- {
- // Changing capitalization. Handle windows case insensitivity
- if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase))
- {
- var tempPath = Path.Combine(rootFolderPath, Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture));
- Directory.Move(currentPath, tempPath);
- currentPath = tempPath;
- }
-
- Directory.Move(currentPath, newPath);
- }
- finally
- {
- CollectionFolder.OnCollectionFolderChange();
-
- Task.Run(() =>
- {
- // No need to start if scanning the library because it will handle it
- if (request.RefreshLibrary)
- {
- _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
- }
- else
- {
- // Need to add a delay here or directory watchers may still pick up the changes
- var task = Task.Delay(1000);
- // Have to block here to allow exceptions to bubble
- Task.WaitAll(task);
-
- _libraryMonitor.Start();
- }
- });
- }
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Delete(RemoveVirtualFolder request)
- {
- return _libraryManager.RemoveVirtualFolder(request.Name, request.RefreshLibrary);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(AddMediaPath request)
- {
- if (string.IsNullOrWhiteSpace(request.Name))
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- _libraryMonitor.Stop();
-
- try
- {
- var mediaPath = request.PathInfo ?? new MediaPathInfo
- {
- Path = request.Path
- };
-
- _libraryManager.AddMediaPath(request.Name, mediaPath);
- }
- finally
- {
- Task.Run(() =>
- {
- // No need to start if scanning the library because it will handle it
- if (request.RefreshLibrary)
- {
- _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
- }
- else
- {
- // Need to add a delay here or directory watchers may still pick up the changes
- var task = Task.Delay(1000);
- // Have to block here to allow exceptions to bubble
- Task.WaitAll(task);
-
- _libraryMonitor.Start();
- }
- });
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(UpdateMediaPath request)
- {
- if (string.IsNullOrWhiteSpace(request.Name))
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- _libraryManager.UpdateMediaPath(request.Name, request.PathInfo);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(RemoveMediaPath request)
- {
- if (string.IsNullOrWhiteSpace(request.Name))
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- _libraryMonitor.Stop();
-
- try
- {
- _libraryManager.RemoveMediaPath(request.Name, request.Path);
- }
- finally
- {
- Task.Run(() =>
- {
- // No need to start if scanning the library because it will handle it
- if (request.RefreshLibrary)
- {
- _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
- }
- else
- {
- // Need to add a delay here or directory watchers may still pick up the changes
- var task = Task.Delay(1000);
- // Have to block here to allow exceptions to bubble
- Task.WaitAll(task);
-
- _libraryMonitor.Start();
- }
- });
- }
- }
- }
-}
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
deleted file mode 100644
index 830372dd8..000000000
--- 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
-{
- /// <summary>
- /// This is insecure right now to avoid windows phone refactoring.
- /// </summary>
- [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
- [Authenticated]
- public class GetLiveTvInfo : IReturn<LiveTvInfo>
- {
- }
-
- [Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
- [Authenticated]
- public class GetChannels : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public ChannelType? Type { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsMovie { get; set; }
-
- [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSeries { get; set; }
-
- [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsNews { get; set; }
-
- [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsKids { get; set; }
-
- [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSports { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "IsFavorite", Description = "Filter by channels that are favorites, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsFavorite { get; set; }
-
- [ApiMember(Name = "IsLiked", Description = "Filter by channels that are liked, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsLiked { get; set; }
-
- [ApiMember(Name = "IsDisliked", Description = "Filter by channels that are disliked, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsDisliked { get; set; }
-
- [ApiMember(Name = "EnableFavoriteSorting", Description = "Incorporate favorite and like status into channel sorting.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool EnableFavoriteSorting { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool AddCurrentProgram { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public string SortBy { get; set; }
-
- public SortOrder? SortOrder { get; set; }
-
- /// <summary>
- /// Gets the order by.
- /// </summary>
- /// <returns>IEnumerable{ItemSortBy}.</returns>
- public string[] GetOrderBy()
- {
- var val = SortBy;
-
- if (string.IsNullOrEmpty(val))
- {
- return Array.Empty<string>();
- }
-
- return val.Split(',');
- }
-
- public GetChannels()
- {
- AddCurrentProgram = true;
- }
- }
-
- [Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
- [Authenticated]
- public class GetChannel : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- [Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
- [Authenticated]
- public class GetRecordings : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ChannelId { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "Status", Description = "Optional filter by recording status.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public RecordingStatus? Status { get; set; }
-
- [ApiMember(Name = "Status", Description = "Optional filter by recordings that are in progress, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsInProgress { get; set; }
-
- [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SeriesTimerId { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public bool? IsMovie { get; set; }
-
- public bool? IsSeries { get; set; }
-
- public bool? IsKids { get; set; }
-
- public bool? IsSports { get; set; }
-
- public bool? IsNews { get; set; }
-
- public bool? IsLibraryItem { get; set; }
-
- public GetRecordings()
- {
- EnableTotalRecordCount = true;
- }
- }
-
- [Route("/LiveTv/Recordings/Series", "GET", Summary = "Gets live tv recordings")]
- [Authenticated]
- public class GetRecordingSeries : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ChannelId { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string UserId { get; set; }
-
- [ApiMember(Name = "GroupId", Description = "Optional filter by recording group.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string GroupId { get; set; }
-
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "Status", Description = "Optional filter by recording status.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public RecordingStatus? Status { get; set; }
-
- [ApiMember(Name = "Status", Description = "Optional filter by recordings that are in progress, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsInProgress { get; set; }
-
- [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SeriesTimerId { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public GetRecordingSeries()
- {
- EnableTotalRecordCount = true;
- }
- }
-
- [Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
- [Authenticated]
- public class GetRecordingGroups : IReturn<QueryResult<BaseItemDto>>
- {
- [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string UserId { get; set; }
- }
-
- [Route("/LiveTv/Recordings/Folders", "GET", Summary = "Gets recording folders")]
- [Authenticated]
- public class GetRecordingFolders : IReturn<BaseItemDto[]>
- {
- [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- [Route("/LiveTv/Recordings/{Id}", "GET", Summary = "Gets a live tv recording")]
- [Authenticated]
- public class GetRecording : IReturn<BaseItemDto>
- {
- [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- [Route("/LiveTv/Tuners/{Id}/Reset", "POST", Summary = "Resets a tv tuner")]
- [Authenticated]
- public class ResetTuner : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Tuner Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/Timers/{Id}", "GET", Summary = "Gets a live tv timer")]
- [Authenticated]
- public class GetTimer : IReturn<TimerInfoDto>
- {
- [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/Timers/Defaults", "GET", Summary = "Gets default values for a new timer")]
- [Authenticated]
- public class GetDefaultTimer : IReturn<SeriesTimerInfoDto>
- {
- [ApiMember(Name = "ProgramId", Description = "Optional, to attach default values based on a program.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ProgramId { get; set; }
- }
-
- [Route("/LiveTv/Timers", "GET", Summary = "Gets live tv timers")]
- [Authenticated]
- public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
- {
- [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ChannelId { get; set; }
-
- [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by timers belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SeriesTimerId { get; set; }
-
- public bool? IsActive { get; set; }
-
- public bool? IsScheduled { get; set; }
- }
-
- [Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
- [Authenticated]
- public class GetPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string ChannelIds { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "MinStartDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string MinStartDate { get; set; }
-
- [ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasAired { get; set; }
-
- public bool? IsAiring { get; set; }
-
- [ApiMember(Name = "MaxStartDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string MaxStartDate { get; set; }
-
- [ApiMember(Name = "MinEndDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string MinEndDate { get; set; }
-
- [ApiMember(Name = "MaxEndDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string MaxEndDate { get; set; }
-
- [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsMovie { get; set; }
-
- [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSeries { get; set; }
-
- [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsNews { get; set; }
-
- [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsKids { get; set; }
-
- [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSports { get; set; }
-
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Name, StartDate", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string SortBy { get; set; }
-
- [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SortOrder { get; set; }
-
- [ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string Genres { get; set; }
-
- [ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string GenreIds { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public string SeriesTimerId { get; set; }
-
- public Guid LibrarySeriesId { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- public GetPrograms()
- {
- EnableTotalRecordCount = true;
- }
- }
-
- [Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
- [Authenticated]
- public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- public bool EnableTotalRecordCount { get; set; }
-
- public GetRecommendedPrograms()
- {
- EnableTotalRecordCount = true;
- }
-
- [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "IsAiring", Description = "Optional. Filter by programs that are currently airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsAiring { get; set; }
-
- [ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasAired { get; set; }
-
- [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSeries { get; set; }
-
- [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsMovie { get; set; }
-
- [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsNews { get; set; }
-
- [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsKids { get; set; }
-
- [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSports { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string GenreIds { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
- }
-
- [Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
- [Authenticated]
- public class GetProgram : IReturn<BaseItemDto>
- {
- [ApiMember(Name = "Id", Description = "Program Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
-
- [Route("/LiveTv/Recordings/{Id}", "DELETE", Summary = "Deletes a live tv recording")]
- [Authenticated]
- public class DeleteRecording : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
- }
-
- [Route("/LiveTv/Timers/{Id}", "DELETE", Summary = "Cancels a live tv timer")]
- [Authenticated]
- public class CancelTimer : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/Timers/{Id}", "POST", Summary = "Updates a live tv timer")]
- [Authenticated]
- public class UpdateTimer : TimerInfoDto, IReturnVoid
- {
- }
-
- [Route("/LiveTv/Timers", "POST", Summary = "Creates a live tv timer")]
- [Authenticated]
- public class CreateTimer : TimerInfoDto, IReturnVoid
- {
- }
-
- [Route("/LiveTv/SeriesTimers/{Id}", "GET", Summary = "Gets a live tv series timer")]
- [Authenticated]
- public class GetSeriesTimer : IReturn<TimerInfoDto>
- {
- [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/SeriesTimers", "GET", Summary = "Gets live tv series timers")]
- [Authenticated]
- public class GetSeriesTimers : IReturn<QueryResult<SeriesTimerInfoDto>>
- {
- [ApiMember(Name = "SortBy", Description = "Optional. Sort by SortName or Priority", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public string SortBy { get; set; }
-
- [ApiMember(Name = "SortOrder", Description = "Optional. Sort in Ascending or Descending order", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
- public SortOrder SortOrder { get; set; }
- }
-
- [Route("/LiveTv/SeriesTimers/{Id}", "DELETE", Summary = "Cancels a live tv series timer")]
- [Authenticated]
- public class CancelSeriesTimer : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/SeriesTimers/{Id}", "POST", Summary = "Updates a live tv series timer")]
- [Authenticated]
- public class UpdateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
- {
- }
-
- [Route("/LiveTv/SeriesTimers", "POST", Summary = "Creates a live tv series timer")]
- [Authenticated]
- public class CreateSeriesTimer : SeriesTimerInfoDto, IReturnVoid
- {
- }
-
- [Route("/LiveTv/Recordings/Groups/{Id}", "GET", Summary = "Gets a recording group")]
- [Authenticated]
- public class GetRecordingGroup : IReturn<BaseItemDto>
- {
- [ApiMember(Name = "Id", Description = "Recording group Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/GuideInfo", "GET", Summary = "Gets guide info")]
- [Authenticated]
- public class GetGuideInfo : IReturn<GuideInfo>
- {
- }
-
- [Route("/LiveTv/TunerHosts", "POST", Summary = "Adds a tuner host")]
- [Authenticated]
- public class AddTunerHost : TunerHostInfo, IReturn<TunerHostInfo>
- {
- }
-
- [Route("/LiveTv/TunerHosts", "DELETE", Summary = "Deletes a tuner host")]
- [Authenticated]
- public class DeleteTunerHost : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Tuner host id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/ListingProviders/Default", "GET")]
- [Authenticated]
- public class GetDefaultListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
- {
- }
-
- [Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
- [Authenticated]
- public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
- {
- public bool ValidateLogin { get; set; }
-
- public bool ValidateListings { get; set; }
-
- public string Pw { get; set; }
- }
-
- [Route("/LiveTv/ListingProviders", "DELETE", Summary = "Deletes a listing provider")]
- [Authenticated]
- public class DeleteListingProvider : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/ListingProviders/Lineups", "GET", Summary = "Gets available lineups")]
- [Authenticated]
- public class GetLineups : IReturn<List<NameIdPair>>
- {
- [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "Type", Description = "Provider Type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Type { get; set; }
-
- [ApiMember(Name = "Location", Description = "Location", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Location { get; set; }
-
- [ApiMember(Name = "Country", Description = "Country", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Country { get; set; }
- }
-
- [Route("/LiveTv/ListingProviders/SchedulesDirect/Countries", "GET", Summary = "Gets available lineups")]
- [Authenticated]
- public class GetSchedulesDirectCountries
- {
- }
-
- [Route("/LiveTv/ChannelMappingOptions")]
- [Authenticated]
- public class GetChannelMappingOptions
- {
- [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query")]
- public string ProviderId { get; set; }
- }
-
- [Route("/LiveTv/ChannelMappings")]
- [Authenticated]
- public class SetChannelMapping
- {
- [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query")]
- public string ProviderId { get; set; }
-
- public string TunerChannelId { get; set; }
-
- public string ProviderChannelId { get; set; }
- }
-
- public class ChannelMappingOptions
- {
- public List<TunerChannelMapping> TunerChannels { get; set; }
-
- public List<NameIdPair> ProviderChannels { get; set; }
-
- public NameValuePair[] Mappings { get; set; }
-
- public string ProviderName { get; set; }
- }
-
- [Route("/LiveTv/LiveStreamFiles/{Id}/stream.{Container}", "GET", Summary = "Gets a live tv channel")]
- public class GetLiveStreamFile
- {
- public string Id { get; set; }
-
- public string Container { get; set; }
- }
-
- [Route("/LiveTv/LiveRecordings/{Id}/stream", "GET", Summary = "Gets a live tv channel")]
- public class GetLiveRecordingFile
- {
- public string Id { get; set; }
- }
-
- [Route("/LiveTv/TunerHosts/Types", "GET")]
- [Authenticated]
- public class GetTunerHostTypes : IReturn<List<NameIdPair>>
- {
- }
-
- [Route("/LiveTv/Tuners/Discvover", "GET")]
- [Authenticated]
- public class DiscoverTuners : IReturn<List<TunerHostInfo>>
- {
- public bool NewDevicesOnly { get; set; }
- }
-
- public class LiveTvService : BaseApiService
- {
- private readonly ILiveTvManager _liveTvManager;
- private readonly IUserManager _userManager;
- private readonly IHttpClient _httpClient;
- private readonly ILibraryManager _libraryManager;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
- private readonly ISessionContext _sessionContext;
- private readonly IStreamHelper _streamHelper;
- private readonly IMediaSourceManager _mediaSourceManager;
-
- public LiveTvService(
- ILogger<LiveTvService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IMediaSourceManager mediaSourceManager,
- IStreamHelper streamHelper,
- ILiveTvManager liveTvManager,
- IUserManager userManager,
- IHttpClient httpClient,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- IAuthorizationContext authContext,
- ISessionContext sessionContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _mediaSourceManager = mediaSourceManager;
- _streamHelper = streamHelper;
- _liveTvManager = liveTvManager;
- _userManager = userManager;
- _httpClient = httpClient;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _authContext = authContext;
- _sessionContext = sessionContext;
- }
-
- public object Get(GetTunerHostTypes request)
- {
- var list = _liveTvManager.GetTunerHostTypes();
- return ToOptimizedResult(list);
- }
-
- public object Get(GetRecordingFolders request)
- {
- var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
- var folders = _liveTvManager.GetRecordingFolders(user);
-
- var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user);
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Count
- };
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetLiveRecordingFile request)
- {
- var path = _liveTvManager.GetEmbyTvActiveRecordingPath(request.Id);
-
- if (string.IsNullOrWhiteSpace(path))
- {
- throw new FileNotFoundException();
- }
-
- var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
- {
- [HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType(path)
- };
-
- return new ProgressiveFileCopier(_streamHelper, path, outputHeaders, Logger)
- {
- AllowEndOfFile = false
- };
- }
-
- public async Task<object> Get(DiscoverTuners request)
- {
- var result = await _liveTvManager.DiscoverTuners(request.NewDevicesOnly, CancellationToken.None).ConfigureAwait(false);
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetLiveStreamFile request)
- {
- var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(request.Id, CancellationToken.None).ConfigureAwait(false);
-
- var directStreamProvider = liveStreamInfo;
-
- var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
- {
- [HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType("file." + request.Container)
- };
-
- return new ProgressiveFileCopier(directStreamProvider, _streamHelper, outputHeaders, Logger)
- {
- AllowEndOfFile = false
- };
- }
-
- public object Get(GetDefaultListingProvider request)
- {
- return ToOptimizedResult(new ListingsProviderInfo());
- }
-
- public async Task<object> Post(SetChannelMapping request)
- {
- return await _liveTvManager.SetChannelMapping(request.ProviderId, request.TunerChannelId, request.ProviderChannelId).ConfigureAwait(false);
- }
-
- public async Task<object> Get(GetChannelMappingOptions request)
- {
- var config = GetConfiguration();
-
- var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
-
- var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name;
-
- var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
- .ConfigureAwait(false);
-
- var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
- .ConfigureAwait(false);
-
- var mappings = listingsProviderInfo.ChannelMappings;
-
- var result = new ChannelMappingOptions
- {
- TunerChannels = tunerChannels.Select(i => _liveTvManager.GetTunerChannelMapping(i, mappings, providerChannels)).ToList(),
-
- ProviderChannels = providerChannels.Select(i => new NameIdPair
- {
- Name = i.Name,
- Id = i.Id
- }).ToList(),
-
- Mappings = mappings,
-
- ProviderName = listingsProviderName
- };
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetSchedulesDirectCountries request)
- {
- // https://json.schedulesdirect.org/20141201/available/countries
-
- var response = await _httpClient.Get(new HttpRequestOptions
- {
- Url = "https://json.schedulesdirect.org/20141201/available/countries",
- BufferContent = false
- }).ConfigureAwait(false);
-
- return ResultFactory.GetResult(Request, response, "application/json");
- }
-
- private void AssertUserCanManageLiveTv()
- {
- var user = _sessionContext.GetUser(Request);
-
- if (user == null)
- {
- throw new SecurityException("Anonymous live tv management is not allowed.");
- }
-
- if (!user.HasPermission(PermissionKind.EnableLiveTvManagement))
- {
- throw new SecurityException("The current user does not have permission to manage live tv.");
- }
- }
-
- public async Task<object> Post(AddListingProvider request)
- {
- if (request.Pw != null)
- {
- request.Password = GetHashedString(request.Pw);
- }
-
- request.Pw = null;
-
- var result = await _liveTvManager.SaveListingProvider(request, request.ValidateLogin, request.ValidateListings).ConfigureAwait(false);
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the hashed string.
- /// </summary>
- private string GetHashedString(string str)
- {
- // SchedulesDirect requires a SHA1 hash of the user's password
- // https://github.com/SchedulesDirect/JSON-Service/wiki/API-20141201#obtain-a-token
- using SHA1 sha = SHA1.Create();
-
- return Hex.Encode(
- sha.ComputeHash(Encoding.UTF8.GetBytes(str)));
- }
-
- public void Delete(DeleteListingProvider request)
- {
- _liveTvManager.DeleteListingsProvider(request.Id);
- }
-
- public async Task<object> Post(AddTunerHost request)
- {
- var result = await _liveTvManager.SaveTunerHost(request).ConfigureAwait(false);
- return ToOptimizedResult(result);
- }
-
- public void Delete(DeleteTunerHost request)
- {
- var config = GetConfiguration();
-
- config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
-
- ServerConfigurationManager.SaveConfiguration("livetv", config);
- }
-
- private LiveTvOptions GetConfiguration()
- {
- return ServerConfigurationManager.GetConfiguration<LiveTvOptions>("livetv");
- }
-
- private void UpdateConfiguration(LiveTvOptions options)
- {
- ServerConfigurationManager.SaveConfiguration("livetv", options);
- }
-
- public async Task<object> Get(GetLineups request)
- {
- var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
-
- return ToOptimizedResult(info);
- }
-
- public object Get(GetLiveTvInfo request)
- {
- var info = _liveTvManager.GetLiveTvInfo(CancellationToken.None);
-
- return ToOptimizedResult(info);
- }
-
- public object Get(GetChannels request)
- {
- var options = GetDtoOptions(_authContext, request);
-
- var channelResult = _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
- {
- ChannelType = request.Type,
- UserId = request.UserId,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- IsFavorite = request.IsFavorite,
- IsLiked = request.IsLiked,
- IsDisliked = request.IsDisliked,
- EnableFavoriteSorting = request.EnableFavoriteSorting,
- IsMovie = request.IsMovie,
- IsSeries = request.IsSeries,
- IsNews = request.IsNews,
- IsKids = request.IsKids,
- IsSports = request.IsSports,
- SortBy = request.GetOrderBy(),
- SortOrder = request.SortOrder ?? SortOrder.Ascending,
- AddCurrentProgram = request.AddCurrentProgram
- }, options, CancellationToken.None);
-
- var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
- RemoveFields(options);
-
- options.AddCurrentProgram = request.AddCurrentProgram;
-
- var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, options, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = channelResult.TotalRecordCount
- };
-
- return ToOptimizedResult(result);
- }
-
- private void RemoveFields(DtoOptions options)
- {
- var fields = options.Fields.ToList();
-
- fields.Remove(ItemFields.CanDelete);
- fields.Remove(ItemFields.CanDownload);
- fields.Remove(ItemFields.DisplayPreferencesId);
- fields.Remove(ItemFields.Etag);
- options.Fields = fields.ToArray();
- }
-
- public object Get(GetChannel request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetPrograms request)
- {
- var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
- var query = new InternalItemsQuery(user)
- {
- ChannelIds = ApiEntryPoint.Split(request.ChannelIds, ',', true).Select(i => new Guid(i)).ToArray(),
- HasAired = request.HasAired,
- IsAiring = request.IsAiring,
- EnableTotalRecordCount = request.EnableTotalRecordCount
- };
-
- if (!string.IsNullOrEmpty(request.MinStartDate))
- {
- query.MinStartDate = DateTime.Parse(request.MinStartDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MinEndDate))
- {
- query.MinEndDate = DateTime.Parse(request.MinEndDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MaxStartDate))
- {
- query.MaxStartDate = DateTime.Parse(request.MaxStartDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MaxEndDate))
- {
- query.MaxEndDate = DateTime.Parse(request.MaxEndDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- query.StartIndex = request.StartIndex;
- query.Limit = request.Limit;
- query.OrderBy = BaseItemsRequest.GetOrderBy(request.SortBy, request.SortOrder);
- query.IsNews = request.IsNews;
- query.IsMovie = request.IsMovie;
- query.IsSeries = request.IsSeries;
- query.IsKids = request.IsKids;
- query.IsSports = request.IsSports;
- query.SeriesTimerId = request.SeriesTimerId;
- query.Genres = (request.Genres ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- query.GenreIds = GetGuids(request.GenreIds);
-
- if (!request.LibrarySeriesId.Equals(Guid.Empty))
- {
- query.IsSeries = true;
-
- if (_libraryManager.GetItemById(request.LibrarySeriesId) is Series series)
- {
- query.Name = series.Name;
- }
- }
-
- var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetRecommendedPrograms request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var query = new InternalItemsQuery(user)
- {
- IsAiring = request.IsAiring,
- Limit = request.Limit,
- HasAired = request.HasAired,
- IsSeries = request.IsSeries,
- IsMovie = request.IsMovie,
- IsKids = request.IsKids,
- IsNews = request.IsNews,
- IsSports = request.IsSports,
- EnableTotalRecordCount = request.EnableTotalRecordCount
- };
-
- query.GenreIds = GetGuids(request.GenreIds);
-
- var result = _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None);
-
- return ToOptimizedResult(result);
- }
-
- public object Post(GetPrograms request)
- {
- return Get(request);
- }
-
- public object Get(GetRecordings request)
- {
- var options = GetDtoOptions(_authContext, request);
-
- var result = _liveTvManager.GetRecordings(new RecordingQuery
- {
- ChannelId = request.ChannelId,
- UserId = request.UserId,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- Status = request.Status,
- SeriesTimerId = request.SeriesTimerId,
- IsInProgress = request.IsInProgress,
- EnableTotalRecordCount = request.EnableTotalRecordCount,
- IsMovie = request.IsMovie,
- IsNews = request.IsNews,
- IsSeries = request.IsSeries,
- IsKids = request.IsKids,
- IsSports = request.IsSports,
- IsLibraryItem = request.IsLibraryItem,
- Fields = request.GetItemFields(),
- ImageTypeLimit = request.ImageTypeLimit,
- EnableImages = request.EnableImages
- }, options);
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetRecordingSeries request)
- {
- return ToOptimizedResult(new QueryResult<BaseItemDto>());
- }
-
- public object Get(GetRecording request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetTimer request)
- {
- var result = await _liveTvManager.GetTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetTimers request)
- {
- var result = await _liveTvManager.GetTimers(new TimerQuery
- {
- ChannelId = request.ChannelId,
- SeriesTimerId = request.SeriesTimerId,
- IsActive = request.IsActive,
- IsScheduled = request.IsScheduled
- }, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public void Delete(DeleteRecording request)
- {
- AssertUserCanManageLiveTv();
-
- _libraryManager.DeleteItem(_libraryManager.GetItemById(request.Id), new DeleteOptions
- {
- DeleteFileLocation = false
- });
- }
-
- public Task Delete(CancelTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.CancelTimer(request.Id);
- }
-
- public Task Post(UpdateTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.UpdateTimer(request, CancellationToken.None);
- }
-
- public async Task<object> Get(GetSeriesTimers request)
- {
- var result = await _liveTvManager.GetSeriesTimers(new SeriesTimerQuery
- {
- SortOrder = request.SortOrder,
- SortBy = request.SortBy
- }, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetSeriesTimer request)
- {
- var result = await _liveTvManager.GetSeriesTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public Task Delete(CancelSeriesTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.CancelSeriesTimer(request.Id);
- }
-
- public Task Post(UpdateSeriesTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.UpdateSeriesTimer(request, CancellationToken.None);
- }
-
- public async Task<object> Get(GetDefaultTimer request)
- {
- if (string.IsNullOrEmpty(request.ProgramId))
- {
- var result = await _liveTvManager.GetNewTimerDefaults(CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
- else
- {
- var result = await _liveTvManager.GetNewTimerDefaults(request.ProgramId, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
- }
-
- public async Task<object> Get(GetProgram request)
- {
- var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
-
- var result = await _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public Task Post(CreateSeriesTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.CreateSeriesTimer(request, CancellationToken.None);
- }
-
- public Task Post(CreateTimer request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.CreateTimer(request, CancellationToken.None);
- }
-
- public object Get(GetRecordingGroups request)
- {
- return ToOptimizedResult(new QueryResult<BaseItemDto>());
- }
-
- public object Get(GetRecordingGroup request)
- {
- throw new FileNotFoundException();
- }
-
- public object Get(GetGuideInfo request)
- {
- return ToOptimizedResult(_liveTvManager.GetGuideInfo());
- }
-
- public Task Post(ResetTuner request)
- {
- AssertUserCanManageLiveTv();
-
- return _liveTvManager.ResetTuner(request.Id, CancellationToken.None);
- }
- }
-}
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
deleted file mode 100644
index d6b5f5195..000000000
--- 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
-{
- /// <summary>
- /// Class GetCultures.
- /// </summary>
- [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
- public class GetCultures : IReturn<CultureDto[]>
- {
- }
-
- /// <summary>
- /// Class GetCountries.
- /// </summary>
- [Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
- public class GetCountries : IReturn<CountryInfo[]>
- {
- }
-
- /// <summary>
- /// Class ParentalRatings.
- /// </summary>
- [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
- public class GetParentalRatings : IReturn<ParentalRating[]>
- {
- }
-
- /// <summary>
- /// Class ParentalRatings.
- /// </summary>
- [Route("/Localization/Options", "GET", Summary = "Gets localization options")]
- public class GetLocalizationOptions : IReturn<LocalizationOption[]>
- {
- }
-
- /// <summary>
- /// Class CulturesService.
- /// </summary>
- [Authenticated(AllowBeforeStartupWizard = true)]
- public class LocalizationService : BaseApiService
- {
- /// <summary>
- /// The _localization.
- /// </summary>
- private readonly ILocalizationManager _localization;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LocalizationService"/> class.
- /// </summary>
- /// <param name="localization">The localization.</param>
- public LocalizationService(
- ILogger<LocalizationService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ILocalizationManager localization)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _localization = localization;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetParentalRatings request)
- {
- var result = _localization.GetParentalRatings();
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetLocalizationOptions request)
- {
- var result = _localization.GetLocalizationOptions();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetCountries request)
- {
- var result = _localization.GetCountries();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetCultures request)
- {
- var result = _localization.GetCultures();
-
- return ToOptimizedResult(result);
- }
- }
-
-}
diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs
deleted file mode 100644
index e9629439d..000000000
--- 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<CollectionCreationResult>
- {
- [ApiMember(Name = "IsLocked", Description = "Whether or not to lock the new collection.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool IsLocked { get; set; }
-
- [ApiMember(Name = "Name", Description = "The name of the new collection.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "ParentId", Description = "Optional - create the collection within a specific folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "Ids", Description = "Item Ids to add to the collection", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string Ids { get; set; }
- }
-
- [Route("/Collections/{Id}/Items", "POST", Summary = "Adds items to a collection")]
- public class AddToCollection : IReturnVoid
- {
- [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Ids { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Collections/{Id}/Items", "DELETE", Summary = "Removes items from a collection")]
- public class RemoveFromCollection : IReturnVoid
- {
- [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string Ids { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Authenticated]
- public class CollectionService : BaseApiService
- {
- private readonly ICollectionManager _collectionManager;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
-
- public CollectionService(
- ILogger<CollectionService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ICollectionManager collectionManager,
- IDtoService dtoService,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _collectionManager = collectionManager;
- _dtoService = dtoService;
- _authContext = authContext;
- }
-
- public object Post(CreateCollection request)
- {
- var userId = _authContext.GetAuthorizationInfo(Request).UserId;
-
- var parentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
-
- var item = _collectionManager.CreateCollection(new CollectionCreationOptions
- {
- IsLocked = request.IsLocked,
- Name = request.Name,
- ParentId = parentId,
- ItemIdList = SplitValue(request.Ids, ','),
- UserIds = new[] { userId }
- });
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
-
- return new CollectionCreationResult
- {
- Id = dto.Id
- };
- }
-
- public void Post(AddToCollection request)
- {
- _collectionManager.AddToCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
- }
-
- public void Delete(RemoveFromCollection request)
- {
- _collectionManager.RemoveFromCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
- }
- }
-}
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
deleted file mode 100644
index 34cccffa3..000000000
--- 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<RecommendationDto[]>, IHasDtoOptions
- {
- [ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int CategoryLimit { get; set; }
-
- [ApiMember(Name = "ItemLimit", Description = "The max number of items to return per category", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int ItemLimit { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Specify this to localize the search to a specific item or folder. Omit to use the root.
- /// </summary>
- /// <value>The parent id.</value>
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- public GetMovieRecommendations()
- {
- CategoryLimit = 5;
- ItemLimit = 8;
- }
-
- public string Fields { get; set; }
- }
-
- /// <summary>
- /// Class MoviesService.
- /// </summary>
- [Authenticated]
- public class MoviesService : BaseApiService
- {
- /// <summary>
- /// The _user manager.
- /// </summary>
- private readonly IUserManager _userManager;
-
- private readonly ILibraryManager _libraryManager;
-
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="MoviesService" /> class.
- /// </summary>
- public MoviesService(
- ILogger<MoviesService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _authContext = authContext;
- }
-
- public object Get(GetMovieRecommendations request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = GetRecommendationCategories(user, request.ParentId, request.CategoryLimit, request.ItemLimit, dtoOptions);
-
- return ToOptimizedResult(result);
- }
-
- public QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var item = string.IsNullOrEmpty(request.Id) ?
- (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
- _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
-
- var itemTypes = new List<string> { typeof(Movie).Name };
- if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(typeof(Trailer).Name);
- itemTypes.Add(typeof(LiveTvProgram).Name);
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- Limit = request.Limit,
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- SimilarTo = item,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
-
- });
-
- var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnList,
-
- TotalRecordCount = itemsResult.Count
- };
-
- return result;
- }
-
- private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
- {
- var categories = new List<RecommendationDto>();
-
- var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? Guid.Empty : new Guid(parentId);
-
- var query = new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[]
- {
- typeof(Movie).Name,
- // typeof(Trailer).Name,
- // typeof(LiveTvProgram).Name
- },
- // IsMovie = true
- OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
- Limit = 7,
- ParentId = parentIdGuid,
- Recursive = true,
- IsPlayed = true,
- DtoOptions = dtoOptions
- };
-
- var recentlyPlayedMovies = _libraryManager.GetItemList(query);
-
- var itemTypes = new List<string> { typeof(Movie).Name };
- if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(typeof(Trailer).Name);
- itemTypes.Add(typeof(LiveTvProgram).Name);
- }
-
- var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
- Limit = 10,
- IsFavoriteOrLiked = true,
- ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(),
- EnableGroupByMetadataKey = true,
- ParentId = parentIdGuid,
- Recursive = true,
- DtoOptions = dtoOptions
- });
-
- var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
- // Get recently played directors
- var recentDirectors = GetDirectors(mostRecentMovies)
- .ToList();
-
- // Get recently played actors
- var recentActors = GetActors(mostRecentMovies)
- .ToList();
-
- var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
- var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
-
- var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
- var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
-
- var categoryTypes = new List<IEnumerator<RecommendationDto>>
- {
- // Give this extra weight
- similarToRecentlyPlayed,
- similarToRecentlyPlayed,
-
- // Give this extra weight
- similarToLiked,
- similarToLiked,
-
- hasDirectorFromRecentlyPlayed,
- hasActorFromRecentlyPlayed
- };
-
- while (categories.Count < categoryLimit)
- {
- var allEmpty = true;
-
- foreach (var category in categoryTypes)
- {
- if (category.MoveNext())
- {
- categories.Add(category.Current);
- allEmpty = false;
-
- if (categories.Count >= categoryLimit)
- {
- break;
- }
- }
- }
-
- if (allEmpty)
- {
- break;
- }
- }
-
- return categories.OrderBy(i => i.RecommendationType);
- }
-
- private IEnumerable<RecommendationDto> GetWithDirector(
- User user,
- IEnumerable<string> names,
- int itemLimit,
- DtoOptions dtoOptions,
- RecommendationType type)
- {
- var itemTypes = new List<string> { typeof(Movie).Name };
- if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(typeof(Trailer).Name);
- itemTypes.Add(typeof(LiveTvProgram).Name);
- }
-
- foreach (var name in names)
- {
- var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- Person = name,
- // Account for duplicates by imdb id, since the database doesn't support this yet
- Limit = itemLimit + 2,
- PersonTypes = new[] { PersonType.Director },
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
- }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
- .Select(x => x.First())
- .Take(itemLimit)
- .ToList();
-
- if (items.Count > 0)
- {
- var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
-
- yield return new RecommendationDto
- {
- BaselineItemName = name,
- CategoryId = name.GetMD5(),
- RecommendationType = type,
- Items = returnItems
- };
- }
- }
- }
-
- private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
- {
- var itemTypes = new List<string> { typeof(Movie).Name };
- if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(typeof(Trailer).Name);
- itemTypes.Add(typeof(LiveTvProgram).Name);
- }
-
- foreach (var name in names)
- {
- var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- Person = name,
- // Account for duplicates by imdb id, since the database doesn't support this yet
- Limit = itemLimit + 2,
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
- }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
- .Select(x => x.First())
- .Take(itemLimit)
- .ToList();
-
- if (items.Count > 0)
- {
- var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
-
- yield return new RecommendationDto
- {
- BaselineItemName = name,
- CategoryId = name.GetMD5(),
- RecommendationType = type,
- Items = returnItems
- };
- }
- }
- }
-
- private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
- {
- var itemTypes = new List<string> { typeof(Movie).Name };
- if (ServerConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(typeof(Trailer).Name);
- itemTypes.Add(typeof(LiveTvProgram).Name);
- }
-
- foreach (var item in baselineItems)
- {
- var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- Limit = itemLimit,
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- SimilarTo = item,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
- });
-
- if (similar.Count > 0)
- {
- var returnItems = _dtoService.GetBaseItemDtos(similar, dtoOptions, user);
-
- yield return new RecommendationDto
- {
- BaselineItemName = item.Name,
- CategoryId = item.Id,
- RecommendationType = type,
- Items = returnItems
- };
- }
- }
- }
-
- private IEnumerable<string> GetActors(List<BaseItem> items)
- {
- var people = _libraryManager.GetPeople(new InternalPeopleQuery
- {
- ExcludePersonTypes = new[]
- {
- PersonType.Director
- },
- MaxListOrder = 3
- });
-
- var itemIds = items.Select(i => i.Id).ToList();
-
- return people
- .Where(i => itemIds.Contains(i.ItemId))
- .Select(i => i.Name)
- .DistinctNames();
- }
-
- private IEnumerable<string> GetDirectors(List<BaseItem> items)
- {
- var people = _libraryManager.GetPeople(new InternalPeopleQuery
- {
- PersonTypes = new[]
- {
- PersonType.Director
- }
- });
-
- var itemIds = items.Select(i => i.Id).ToList();
-
- return people
- .Where(i => itemIds.Contains(i.ItemId))
- .Select(i => i.Name)
- .DistinctNames();
- }
- }
-}
diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs
deleted file mode 100644
index ca9f9d03b..000000000
--- 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<QueryResult<BaseItemDto>>
- {
- }
-
- /// <summary>
- /// Class TrailersService.
- /// </summary>
- [Authenticated]
- public class TrailersService : BaseApiService
- {
- /// <summary>
- /// The _user manager.
- /// </summary>
- private readonly IUserManager _userManager;
-
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
-
- /// <summary>
- /// The logger for the created <see cref="ItemsService"/> instances.
- /// </summary>
- private readonly ILogger<ItemsService> _logger;
-
- private readonly IDtoService _dtoService;
- private readonly ILocalizationManager _localizationManager;
- private readonly IJsonSerializer _json;
- private readonly IAuthorizationContext _authContext;
-
- public TrailersService(
- ILoggerFactory loggerFactory,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- ILocalizationManager localizationManager,
- IJsonSerializer json,
- IAuthorizationContext authContext)
- : base(loggerFactory.CreateLogger<TrailersService>(), serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _localizationManager = localizationManager;
- _json = json;
- _authContext = authContext;
- _logger = loggerFactory.CreateLogger<ItemsService>();
- }
-
- public object Get(Getrailers request)
- {
- var json = _json.SerializeToString(request);
- var getItems = _json.DeserializeFromString<GetItems>(json);
-
- getItems.IncludeItemTypes = "Trailer";
-
- return new ItemsService(
- _logger,
- ServerConfigurationManager,
- ResultFactory,
- _userManager,
- _libraryManager,
- _localizationManager,
- _dtoService,
- _authContext)
- {
- Request = Request,
- }.Get(getItems);
- }
- }
-}
diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs
deleted file mode 100644
index 74d3cce12..000000000
--- 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
- {
- /// <summary>
- /// The _user manager.
- /// </summary>
- private readonly IUserManager _userManager;
-
- /// <summary>
- /// The _user data repository.
- /// </summary>
- private readonly IUserDataManager _userDataRepository;
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly IItemRepository _itemRepo;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
-
- public AlbumsService(
- ILogger<AlbumsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- IUserDataManager userDataRepository,
- ILibraryManager libraryManager,
- IItemRepository itemRepo,
- IDtoService dtoService,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _userDataRepository = userDataRepository;
- _libraryManager = libraryManager;
- _itemRepo = itemRepo;
- _dtoService = dtoService;
- _authContext = authContext;
- }
-
- public object Get(GetSimilarArtists request)
- {
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = SimilarItemsHelper.GetSimilarItemsResult(
- dtoOptions,
- _userManager,
- _itemRepo,
- _libraryManager,
- _userDataRepository,
- _dtoService,
- request, new[] { typeof(MusicArtist) },
- SimilarItemsHelper.GetSimiliarityScore);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSimilarAlbums request)
- {
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = SimilarItemsHelper.GetSimilarItemsResult(
- dtoOptions,
- _userManager,
- _itemRepo,
- _libraryManager,
- _userDataRepository,
- _dtoService,
- request, new[] { typeof(MusicAlbum) },
- GetAlbumSimilarityScore);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the album similarity score.
- /// </summary>
- /// <param name="item1">The item1.</param>
- /// <param name="item1People">The item1 people.</param>
- /// <param name="allPeople">All people.</param>
- /// <param name="item2">The item2.</param>
- /// <returns>System.Int32.</returns>
- private int GetAlbumSimilarityScore(BaseItem item1, List<PersonInfo> item1People, List<PersonInfo> allPeople, BaseItem item2)
- {
- var points = SimilarItemsHelper.GetSimiliarityScore(item1, item1People, allPeople, item2);
-
- var album1 = (MusicAlbum)item1;
- var album2 = (MusicAlbum)item2;
-
- var artists1 = album1
- .GetAllArtists()
- .DistinctNames()
- .ToList();
-
- var artists2 = new HashSet<string>(
- album2.GetAllArtists().DistinctNames(),
- StringComparer.OrdinalIgnoreCase);
-
- return points + artists1.Where(artists2.Contains).Sum(i => 5);
- }
- }
-}
diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs
deleted file mode 100644
index ebd3eb64a..000000000
--- 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<InstantMixService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- IDtoService dtoService,
- IMusicManager musicManager,
- ILibraryManager libraryManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _dtoService = dtoService;
- _musicManager = musicManager;
- _libraryManager = libraryManager;
- _authContext = authContext;
- }
-
- public object Get(GetInstantMixFromItem request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromArtistId request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromMusicGenreId request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromSong request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromAlbum request)
- {
- var album = _libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromPlaylist request)
- {
- var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- public object Get(GetInstantMixFromMusicGenre request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var items = _musicManager.GetInstantMixFromGenres(new[] { request.Name }, user, dtoOptions);
-
- return GetResult(items, user, request, dtoOptions);
- }
-
- private object GetResult(List<BaseItem> items, User user, BaseGetSimilarItems request, DtoOptions dtoOptions)
- {
- var list = items;
-
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = list.Count
- };
-
- if (request.Limit.HasValue)
- {
- list = list.Take(request.Limit.Value).ToList();
- }
-
- var returnList = _dtoService.GetBaseItemDtos(list, dtoOptions, user);
-
- result.Items = returnList;
-
- return result;
- }
- }
-}
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
deleted file mode 100644
index a84556fcc..000000000
--- 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<RepositoryInfo>, IReturnVoid
- {
- }
-
- /// <summary>
- /// Class GetPackage.
- /// </summary>
- [Route("/Packages/{Name}", "GET", Summary = "Gets a package, by name or assembly guid")]
- [Authenticated]
- public class GetPackage : IReturn<PackageInfo>
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The name of the package", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "AssemblyGuid", Description = "The guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string AssemblyGuid { get; set; }
- }
-
- /// <summary>
- /// Class GetPackages.
- /// </summary>
- [Route("/Packages", "GET", Summary = "Gets available packages")]
- [Authenticated]
- public class GetPackages : IReturn<PackageInfo[]>
- {
- }
-
- /// <summary>
- /// Class InstallPackage.
- /// </summary>
- [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")]
- [Authenticated(Roles = "Admin")]
- public class InstallPackage : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "Package name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "AssemblyGuid", Description = "Guid of the associated assembly", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string AssemblyGuid { get; set; }
-
- /// <summary>
- /// Gets or sets the version.
- /// </summary>
- /// <value>The version.</value>
- [ApiMember(Name = "Version", Description = "Optional version. Defaults to latest version.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Version { get; set; }
- }
-
- /// <summary>
- /// Class CancelPackageInstallation.
- /// </summary>
- [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")]
- [Authenticated(Roles = "Admin")]
- public class CancelPackageInstallation : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Installation Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class PackageService.
- /// </summary>
- public class PackageService : BaseApiService
- {
- private readonly IInstallationManager _installationManager;
- private readonly IServerConfigurationManager _serverConfigurationManager;
-
- public PackageService(
- ILogger<PackageService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IInstallationManager installationManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _installationManager = installationManager;
- _serverConfigurationManager = serverConfigurationManager;
- }
-
- public object Get(GetRepositories request)
- {
- var result = _serverConfigurationManager.Configuration.PluginRepositories;
- return ToOptimizedResult(result);
- }
-
- public void Post(SetRepositories request)
- {
- _serverConfigurationManager.Configuration.PluginRepositories = request;
- _serverConfigurationManager.SaveConfiguration();
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPackage request)
- {
- var packages = _installationManager.GetAvailablePackages().GetAwaiter().GetResult();
- var result = _installationManager.FilterPackages(
- packages,
- request.Name,
- string.IsNullOrEmpty(request.AssemblyGuid) ? default : Guid.Parse(request.AssemblyGuid)).FirstOrDefault();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Get(GetPackages request)
- {
- IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
-
- return ToOptimizedResult(packages.ToArray());
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <exception cref="ResourceNotFoundException"></exception>
- public async Task Post(InstallPackage request)
- {
- var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
- var package = _installationManager.GetCompatibleVersions(
- packages,
- request.Name,
- string.IsNullOrEmpty(request.AssemblyGuid) ? Guid.Empty : Guid.Parse(request.AssemblyGuid),
- string.IsNullOrEmpty(request.Version) ? null : Version.Parse(request.Version)).FirstOrDefault();
-
- if (package == null)
- {
- throw new ResourceNotFoundException(
- string.Format(
- CultureInfo.InvariantCulture,
- "Package not found: {0}",
- request.Name));
- }
-
- await _installationManager.InstallPackage(package);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(CancelPackageInstallation request)
- {
- _installationManager.CancelInstallation(new Guid(request.Id));
- }
- }
-}
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
deleted file mode 100644
index 5513c0892..000000000
--- 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<PlaylistCreationResult>
- {
- [ApiMember(Name = "Name", Description = "The name of the new playlist.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Ids", Description = "Item Ids to add to the playlist", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string Ids { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "MediaType", Description = "The playlist media type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaType { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "POST", Summary = "Adds items to a playlist")]
- public class AddToPlaylist : IReturnVoid
- {
- [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Ids { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public Guid UserId { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items/{ItemId}/Move/{NewIndex}", "POST", Summary = "Moves a playlist item")]
- public class MoveItem : IReturnVoid
- {
- [ApiMember(Name = "ItemId", Description = "ItemId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "NewIndex", Description = "NewIndex", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public int NewIndex { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "DELETE", Summary = "Removes items from a playlist")]
- public class RemoveFromPlaylist : IReturnVoid
- {
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
-
- [ApiMember(Name = "EntryIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string EntryIds { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "GET", Summary = "Gets the original items of a playlist")]
- public class GetPlaylistItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
- }
-
- [Authenticated]
- public class PlaylistService : BaseApiService
- {
- private readonly IPlaylistManager _playlistManager;
- private readonly IDtoService _dtoService;
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
- private readonly IAuthorizationContext _authContext;
-
- public PlaylistService(
- ILogger<PlaylistService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IDtoService dtoService,
- IPlaylistManager playlistManager,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _dtoService = dtoService;
- _playlistManager = playlistManager;
- _userManager = userManager;
- _libraryManager = libraryManager;
- _authContext = authContext;
- }
-
- public void Post(MoveItem request)
- {
- _playlistManager.MoveItem(request.Id, request.ItemId, request.NewIndex);
- }
-
- public async Task<object> Post(CreatePlaylist request)
- {
- var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
- {
- Name = request.Name,
- ItemIdList = GetGuids(request.Ids),
- UserId = request.UserId,
- MediaType = request.MediaType
- }).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public void Post(AddToPlaylist request)
- {
- _playlistManager.AddToPlaylist(request.Id, GetGuids(request.Ids), request.UserId);
- }
-
- public void Delete(RemoveFromPlaylist request)
- {
- _playlistManager.RemoveFromPlaylist(request.Id, request.EntryIds.Split(','));
- }
-
- public object Get(GetPlaylistItems request)
- {
- var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var items = playlist.GetManageableItems().ToArray();
-
- var count = items.Length;
-
- if (request.StartIndex.HasValue)
- {
- items = items.Skip(request.StartIndex.Value).ToArray();
- }
-
- if (request.Limit.HasValue)
- {
- items = items.Take(request.Limit.Value).ToArray();
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
-
- for (int index = 0; index < dtos.Count; index++)
- {
- dtos[index].PlaylistItemId = items[index].Item1.Id;
- }
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = count
- };
-
- return ToOptimizedResult(result);
- }
- }
-}
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs
deleted file mode 100644
index 7d976ceaa..000000000
--- 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
-{
- /// <summary>
- /// Class Plugins.
- /// </summary>
- [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
- [Authenticated]
- public class GetPlugins : IReturn<PluginInfo[]>
- {
- public bool? IsAppStoreEnabled { get; set; }
- }
-
- /// <summary>
- /// Class UninstallPlugin.
- /// </summary>
- [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
- [Authenticated(Roles = "Admin")]
- public class UninstallPlugin : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetPluginConfiguration.
- /// </summary>
- [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")]
- [Authenticated]
- public class GetPluginConfiguration
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class UpdatePluginConfiguration.
- /// </summary>
- [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")]
- [Authenticated]
- public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Plugin Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// The raw Http Request Input Stream.
- /// </summary>
- /// <value>The request stream.</value>
- public Stream RequestStream { get; set; }
- }
-
- // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins,
- // delete all these registration endpoints. They are only kept for compatibility.
- [Route("/Registrations/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
- [Authenticated]
- public class GetRegistration : IReturn<RegistrationInfo>
- {
- [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
- }
-
- /// <summary>
- /// Class GetPluginSecurityInfo.
- /// </summary>
- [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information", IsHidden = true)]
- [Authenticated]
- public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
- {
- }
-
- /// <summary>
- /// Class UpdatePluginSecurityInfo.
- /// </summary>
- [Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information", IsHidden = true)]
- [Authenticated(Roles = "Admin")]
- public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
- {
- }
-
- [Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)]
- [Authenticated]
- public class GetRegistrationStatus
- {
- [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
- }
-
- // TODO these two classes are only kept for compability with paid plugins and should be removed
- public class RegistrationInfo
- {
- public string Name { get; set; }
-
- public DateTime ExpirationDate { get; set; }
-
- public bool IsTrial { get; set; }
-
- public bool IsRegistered { get; set; }
- }
-
- public class MBRegistrationRecord
- {
- public DateTime ExpirationDate { get; set; }
-
- public bool IsRegistered { get; set; }
-
- public bool RegChecked { get; set; }
-
- public bool RegError { get; set; }
-
- public bool TrialVersion { get; set; }
-
- public bool IsValid { get; set; }
- }
-
- public class PluginSecurityInfo
- {
- public string SupporterKey { get; set; }
-
- public bool IsMBSupporter { get; set; }
- }
- /// <summary>
- /// Class PluginsService.
- /// </summary>
- public class PluginService : BaseApiService
- {
- /// <summary>
- /// The _json serializer.
- /// </summary>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// The _app host.
- /// </summary>
- private readonly IApplicationHost _appHost;
- private readonly IInstallationManager _installationManager;
-
- public PluginService(
- ILogger<PluginService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IJsonSerializer jsonSerializer,
- IApplicationHost appHost,
- IInstallationManager installationManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _appHost = appHost;
- _installationManager = installationManager;
- _jsonSerializer = jsonSerializer;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetRegistrationStatus request)
- {
- var record = new MBRegistrationRecord
- {
- IsRegistered = true,
- RegChecked = true,
- TrialVersion = false,
- IsValid = true,
- RegError = false
- };
-
- return ToOptimizedResult(record);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPlugins request)
- {
- var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray();
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPluginConfiguration request)
- {
- var guid = new Guid(request.Id);
- var plugin = _appHost.Plugins.First(p => p.Id == guid) as IHasPluginConfiguration;
-
- return ToOptimizedResult(plugin.Configuration);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPluginSecurityInfo request)
- {
- var result = new PluginSecurityInfo
- {
- IsMBSupporter = true,
- SupporterKey = "IAmTotallyLegit"
- };
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(UpdatePluginSecurityInfo request)
- {
- return Task.CompletedTask;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public async Task Post(UpdatePluginConfiguration request)
- {
- // We need to parse this manually because we told service stack not to with IRequiresRequestStream
- // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
- var id = Guid.Parse(GetPathValue(1));
-
- if (!(_appHost.Plugins.First(p => p.Id == id) is IHasPluginConfiguration plugin))
- {
- throw new FileNotFoundException();
- }
-
- var configuration = (await _jsonSerializer.DeserializeFromStreamAsync(request.RequestStream, plugin.ConfigurationType).ConfigureAwait(false)) as BasePluginConfiguration;
-
- plugin.UpdateConfiguration(configuration);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(UninstallPlugin request)
- {
- var guid = new Guid(request.Id);
- var plugin = _appHost.Plugins.First(p => p.Id == guid);
-
- _installationManager.UninstallPlugin(plugin);
- }
- }
-}
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
deleted file mode 100644
index 86b00316a..000000000
--- 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
-{
- /// <summary>
- /// Class GetScheduledTask.
- /// </summary>
- [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
- public class GetScheduledTask : IReturn<TaskInfo>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetScheduledTasks.
- /// </summary>
- [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
- public class GetScheduledTasks : IReturn<TaskInfo[]>
- {
- [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsHidden { get; set; }
-
- [ApiMember(Name = "IsEnabled", Description = "Optional filter tasks that are enabled, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsEnabled { get; set; }
- }
-
- /// <summary>
- /// Class StartScheduledTask.
- /// </summary>
- [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
- public class StartScheduledTask : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class StopScheduledTask.
- /// </summary>
- [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
- public class StopScheduledTask : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class UpdateScheduledTaskTriggers.
- /// </summary>
- [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
- public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the task id.
- /// </summary>
- /// <value>The task id.</value>
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class ScheduledTasksService.
- /// </summary>
- [Authenticated(Roles = "Admin")]
- public class ScheduledTaskService : BaseApiService
- {
- /// <summary>
- /// The task manager.
- /// </summary>
- private readonly ITaskManager _taskManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ScheduledTaskService" /> class.
- /// </summary>
- /// <param name="taskManager">The task manager.</param>
- /// <exception cref="ArgumentNullException">taskManager</exception>
- public ScheduledTaskService(
- ILogger<ScheduledTaskService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ITaskManager taskManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _taskManager = taskManager;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>IEnumerable{TaskInfo}.</returns>
- public object Get(GetScheduledTasks request)
- {
- IEnumerable<IScheduledTaskWorker> result = _taskManager.ScheduledTasks
- .OrderBy(i => i.Name);
-
- if (request.IsHidden.HasValue)
- {
- var val = request.IsHidden.Value;
-
- result = result.Where(i =>
- {
- var isHidden = false;
-
- if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
- {
- isHidden = configurableTask.IsHidden;
- }
-
- return isHidden == val;
- });
- }
-
- if (request.IsEnabled.HasValue)
- {
- var val = request.IsEnabled.Value;
-
- result = result.Where(i =>
- {
- var isEnabled = true;
-
- if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
- {
- isEnabled = configurableTask.IsEnabled;
- }
-
- return isEnabled == val;
- });
- }
-
- var infos = result
- .Select(ScheduledTaskHelpers.GetTaskInfo)
- .ToArray();
-
- return ToOptimizedResult(infos);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>IEnumerable{TaskInfo}.</returns>
- /// <exception cref="ResourceNotFoundException">Task not found</exception>
- public object Get(GetScheduledTask request)
- {
- var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
- if (task == null)
- {
- throw new ResourceNotFoundException("Task not found");
- }
-
- var result = ScheduledTaskHelpers.GetTaskInfo(task);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <exception cref="ResourceNotFoundException">Task not found</exception>
- public void Post(StartScheduledTask request)
- {
- var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
- if (task == null)
- {
- throw new ResourceNotFoundException("Task not found");
- }
-
- _taskManager.Execute(task, new TaskOptions());
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <exception cref="ResourceNotFoundException">Task not found</exception>
- public void Delete(StopScheduledTask request)
- {
- var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
- if (task == null)
- {
- throw new ResourceNotFoundException("Task not found");
- }
-
- _taskManager.Cancel(task);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <exception cref="ResourceNotFoundException">Task not found</exception>
- public void Post(UpdateScheduledTaskTriggers request)
- {
- // We need to parse this manually because we told service stack not to with IRequiresRequestStream
- // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
- var id = GetPathValue(1).ToString();
-
- var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.Ordinal));
-
- if (task == null)
- {
- throw new ResourceNotFoundException("Task not found");
- }
-
- task.Triggers = request.ToArray();
- }
- }
-}
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
deleted file mode 100644
index 64ee69300..000000000
--- 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
-{
- /// <summary>
- /// Class GetSearchHints.
- /// </summary>
- [Route("/Search/Hints", "GET", Summary = "Gets search hints based on a search term")]
- public class GetSearchHints : IReturn<SearchHintResult>
- {
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Supply a user id to search within a user's library or omit to search all.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Search characters used to find items.
- /// </summary>
- /// <value>The index by.</value>
- [ApiMember(Name = "SearchTerm", Description = "The search term to filter on", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SearchTerm { get; set; }
-
-
- [ApiMember(Name = "IncludePeople", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludePeople { get; set; }
-
- [ApiMember(Name = "IncludeMedia", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludeMedia { get; set; }
-
- [ApiMember(Name = "IncludeGenres", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludeGenres { get; set; }
-
- [ApiMember(Name = "IncludeStudios", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludeStudios { get; set; }
-
- [ApiMember(Name = "IncludeArtists", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool IncludeArtists { get; set; }
-
- [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string IncludeItemTypes { get; set; }
-
- [ApiMember(Name = "ExcludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeItemTypes { get; set; }
-
- [ApiMember(Name = "MediaTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string MediaTypes { get; set; }
-
- public string ParentId { get; set; }
-
- [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsMovie { get; set; }
-
- [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSeries { get; set; }
-
- [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsNews { get; set; }
-
- [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsKids { get; set; }
-
- [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
- public bool? IsSports { get; set; }
-
- public GetSearchHints()
- {
- IncludeArtists = true;
- IncludeGenres = true;
- IncludeMedia = true;
- IncludePeople = true;
- IncludeStudios = true;
- }
- }
-
- /// <summary>
- /// Class SearchService.
- /// </summary>
- [Authenticated]
- public class SearchService : BaseApiService
- {
- /// <summary>
- /// The _search engine.
- /// </summary>
- private readonly ISearchEngine _searchEngine;
- private readonly ILibraryManager _libraryManager;
- private readonly IDtoService _dtoService;
- private readonly IImageProcessor _imageProcessor;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SearchService" /> class.
- /// </summary>
- /// <param name="searchEngine">The search engine.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="dtoService">The dto service.</param>
- /// <param name="imageProcessor">The image processor.</param>
- public SearchService(
- ILogger<SearchService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ISearchEngine searchEngine,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- IImageProcessor imageProcessor)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _searchEngine = searchEngine;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _imageProcessor = imageProcessor;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSearchHints request)
- {
- var result = GetSearchHintsAsync(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the search hints async.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{IEnumerable{SearchHintResult}}.</returns>
- private SearchHintResult GetSearchHintsAsync(GetSearchHints request)
- {
- var result = _searchEngine.GetSearchHints(new SearchQuery
- {
- Limit = request.Limit,
- SearchTerm = request.SearchTerm,
- IncludeArtists = request.IncludeArtists,
- IncludeGenres = request.IncludeGenres,
- IncludeMedia = request.IncludeMedia,
- IncludePeople = request.IncludePeople,
- IncludeStudios = request.IncludeStudios,
- StartIndex = request.StartIndex,
- UserId = request.UserId,
- IncludeItemTypes = ApiEntryPoint.Split(request.IncludeItemTypes, ',', true),
- ExcludeItemTypes = ApiEntryPoint.Split(request.ExcludeItemTypes, ',', true),
- MediaTypes = ApiEntryPoint.Split(request.MediaTypes, ',', true),
- ParentId = request.ParentId,
-
- IsKids = request.IsKids,
- IsMovie = request.IsMovie,
- IsNews = request.IsNews,
- IsSeries = request.IsSeries,
- IsSports = request.IsSports
- });
-
- return new SearchHintResult
- {
- TotalRecordCount = result.TotalRecordCount,
-
- SearchHints = result.Items.Select(GetSearchHintResult).ToArray()
- };
- }
-
- /// <summary>
- /// Gets the search hint result.
- /// </summary>
- /// <param name="hintInfo">The hint info.</param>
- /// <returns>SearchHintResult.</returns>
- private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
- {
- var item = hintInfo.Item;
-
- var result = new SearchHint
- {
- Name = item.Name,
- IndexNumber = item.IndexNumber,
- ParentIndexNumber = item.ParentIndexNumber,
- Id = item.Id,
- Type = item.GetClientTypeName(),
- MediaType = item.MediaType,
- MatchedTerm = hintInfo.MatchedTerm,
- RunTimeTicks = item.RunTimeTicks,
- ProductionYear = item.ProductionYear,
- ChannelId = item.ChannelId,
- EndDate = item.EndDate
- };
-
- // legacy
- result.ItemId = result.Id;
-
- if (item.IsFolder)
- {
- result.IsFolder = true;
- }
-
- var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
-
- if (primaryImageTag != null)
- {
- result.PrimaryImageTag = primaryImageTag;
- result.PrimaryImageAspectRatio = _dtoService.GetPrimaryImageAspectRatio(item);
- }
-
- SetThumbImageInfo(result, item);
- SetBackdropImageInfo(result, item);
-
- switch (item)
- {
- case IHasSeries hasSeries:
- result.Series = hasSeries.SeriesName;
- break;
- case LiveTvProgram program:
- result.StartDate = program.StartDate;
- break;
- case Series series:
- if (series.Status.HasValue)
- {
- result.Status = series.Status.Value.ToString();
- }
-
- break;
- case MusicAlbum album:
- result.Artists = album.Artists;
- result.AlbumArtist = album.AlbumArtist;
- break;
- case Audio song:
- result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
- result.Artists = song.Artists;
-
- MusicAlbum musicAlbum = song.AlbumEntity;
-
- if (musicAlbum != null)
- {
- result.Album = musicAlbum.Name;
- result.AlbumId = musicAlbum.Id;
- }
- else
- {
- result.Album = song.Album;
- }
-
- break;
- }
-
- if (!item.ChannelId.Equals(Guid.Empty))
- {
- var channel = _libraryManager.GetItemById(item.ChannelId);
- result.ChannelName = channel?.Name;
- }
-
- return result;
- }
-
- private void SetThumbImageInfo(SearchHint hint, BaseItem item)
- {
- var itemWithImage = item.HasImage(ImageType.Thumb) ? item : null;
-
- if (itemWithImage == null && item is Episode)
- {
- itemWithImage = GetParentWithImage<Series>(item, ImageType.Thumb);
- }
-
- if (itemWithImage == null)
- {
- itemWithImage = GetParentWithImage<BaseItem>(item, ImageType.Thumb);
- }
-
- if (itemWithImage != null)
- {
- var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Thumb);
-
- if (tag != null)
- {
- hint.ThumbImageTag = tag;
- hint.ThumbImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
- }
- }
- }
-
- private void SetBackdropImageInfo(SearchHint hint, BaseItem item)
- {
- var itemWithImage = (item.HasImage(ImageType.Backdrop) ? item : null)
- ?? GetParentWithImage<BaseItem>(item, ImageType.Backdrop);
-
- if (itemWithImage != null)
- {
- var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Backdrop);
-
- if (tag != null)
- {
- hint.BackdropImageTag = tag;
- hint.BackdropImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
- }
- }
- }
-
- private T GetParentWithImage<T>(BaseItem item, ImageType type)
- where T : BaseItem
- {
- return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
- }
- }
-}
diff --git a/MediaBrowser.Api/Sessions/SessionService.cs b/MediaBrowser.Api/Sessions/SessionService.cs
deleted file mode 100644
index 50adc5698..000000000
--- 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
-{
- /// <summary>
- /// Class GetSessions.
- /// </summary>
- [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
- [Authenticated]
- public class GetSessions : IReturn<SessionInfo[]>
- {
- [ApiMember(Name = "ControllableByUserId", Description = "Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid ControllableByUserId { get; set; }
-
- [ApiMember(Name = "DeviceId", Description = "Filter by device Id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string DeviceId { get; set; }
-
- public int? ActiveWithinSeconds { get; set; }
- }
-
- /// <summary>
- /// Class DisplayContent.
- /// </summary>
- [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")]
- [Authenticated]
- public class DisplayContent : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Artist, Genre, Studio, Person, or any kind of BaseItem.
- /// </summary>
- /// <value>The type of the item.</value>
- [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemType { get; set; }
-
- /// <summary>
- /// Artist name, genre name, item Id, etc.
- /// </summary>
- /// <value>The item identifier.</value>
- [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the item.
- /// </summary>
- /// <value>The name of the item.</value>
- [ApiMember(Name = "ItemName", Description = "The name of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemName { get; set; }
- }
-
- [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")]
- [Authenticated]
- public class Play : PlayRequest
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
- [Authenticated]
- public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendSystemCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the command.
- /// </summary>
- /// <value>The play command.</value>
- [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Command { get; set; }
- }
-
- [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendGeneralCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the command.
- /// </summary>
- /// <value>The play command.</value>
- [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Command { get; set; }
- }
-
- [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendFullGeneralCommand : GeneralCommand, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
- [Authenticated]
- public class SendMessageCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "Text", Description = "The message text.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Text { get; set; }
-
- [ApiMember(Name = "Header", Description = "The message header.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Header { get; set; }
-
- [ApiMember(Name = "TimeoutMs", Description = "The message timeout. If omitted the user will have to confirm viewing the message.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public long? TimeoutMs { get; set; }
- }
-
- [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")]
- [Authenticated]
- public class AddUserToSession : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")]
- [Authenticated]
- public class RemoveUserFromSession : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")]
- [Authenticated]
- public class PostCapabilities : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlayableMediaTypes { get; set; }
-
- [ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string SupportedCommands { get; set; }
-
- [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsMediaControl { get; set; }
-
- [ApiMember(Name = "SupportsSync", Description = "Determines whether sync is supported.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsSync { get; set; }
-
- [ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsPersistentIdentifier { get; set; }
-
- public PostCapabilities()
- {
- SupportsPersistentIdentifier = true;
- }
- }
-
- [Route("/Sessions/Capabilities/Full", "POST", Summary = "Updates capabilities for a device")]
- [Authenticated]
- public class PostFullCapabilities : ClientCapabilities, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/Viewing", "POST", Summary = "Reports that a session is viewing an item")]
- [Authenticated]
- public class ReportViewing : IReturnVoid
- {
- [ApiMember(Name = "SessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string SessionId { get; set; }
-
- [ApiMember(Name = "ItemId", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
- }
-
- [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
- [Authenticated]
- public class ReportSessionEnded : IReturnVoid
- {
- }
-
- [Route("/Auth/Providers", "GET")]
- [Authenticated(Roles = "Admin")]
- public class GetAuthProviders : IReturn<NameIdPair[]>
- {
- }
-
- [Route("/Auth/PasswordResetProviders", "GET")]
- [Authenticated(Roles = "Admin")]
- public class GetPasswordResetProviders : IReturn<NameIdPair[]>
- {
- }
-
- /// <summary>
- /// Class SessionsService.
- /// </summary>
- public class SessionService : BaseApiService
- {
- /// <summary>
- /// The session manager.
- /// </summary>
- private readonly ISessionManager _sessionManager;
-
- private readonly IUserManager _userManager;
- private readonly IAuthorizationContext _authContext;
- private readonly IDeviceManager _deviceManager;
- private readonly ISessionContext _sessionContext;
-
- public SessionService(
- ILogger<SessionService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ISessionManager sessionManager,
- IUserManager userManager,
- IAuthorizationContext authContext,
- IDeviceManager deviceManager,
- ISessionContext sessionContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _sessionManager = sessionManager;
- _userManager = userManager;
- _authContext = authContext;
- _deviceManager = deviceManager;
- _sessionContext = sessionContext;
- }
-
- public object Get(GetAuthProviders request)
- {
- return _userManager.GetAuthenticationProviders();
- }
-
- public object Get(GetPasswordResetProviders request)
- {
- return _userManager.GetPasswordResetProviders();
- }
-
- public void Post(ReportSessionEnded request)
- {
- var auth = _authContext.GetAuthorizationInfo(Request);
-
- _sessionManager.Logout(auth.Token);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSessions request)
- {
- var result = _sessionManager.Sessions;
-
- if (!string.IsNullOrEmpty(request.DeviceId))
- {
- result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase));
- }
-
- if (!request.ControllableByUserId.Equals(Guid.Empty))
- {
- result = result.Where(i => i.SupportsRemoteControl);
-
- var user = _userManager.GetUserById(request.ControllableByUserId);
-
- if (!user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers))
- {
- result = result.Where(i => i.UserId.Equals(Guid.Empty) || i.ContainsUser(request.ControllableByUserId));
- }
-
- if (!user.HasPermission(PermissionKind.EnableSharedDeviceControl))
- {
- result = result.Where(i => !i.UserId.Equals(Guid.Empty));
- }
-
- if (request.ActiveWithinSeconds.HasValue && request.ActiveWithinSeconds.Value > 0)
- {
- var minActiveDate = DateTime.UtcNow.AddSeconds(0 - request.ActiveWithinSeconds.Value);
- result = result.Where(i => i.LastActivityDate >= minActiveDate);
- }
-
- result = result.Where(i =>
- {
- var deviceId = i.DeviceId;
-
- if (!string.IsNullOrWhiteSpace(deviceId))
- {
- if (!_deviceManager.CanAccessDevice(user, deviceId))
- {
- return false;
- }
- }
-
- return true;
- });
- }
-
- return ToOptimizedResult(result.ToArray());
- }
-
- public Task Post(SendPlaystateCommand request)
- {
- return _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(DisplayContent request)
- {
- var command = new BrowseRequest
- {
- ItemId = request.ItemId,
- ItemName = request.ItemName,
- ItemType = request.ItemType
- };
-
- return _sessionManager.SendBrowseCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(SendSystemCommand request)
- {
- var name = request.Command;
- if (Enum.TryParse(name, true, out GeneralCommandType commandType))
- {
- name = commandType.ToString();
- }
-
- var currentSession = GetSession(_sessionContext);
- var command = new GeneralCommand
- {
- Name = name,
- ControllingUserId = currentSession.UserId
- };
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(SendMessageCommand request)
- {
- var command = new MessageCommand
- {
- Header = string.IsNullOrEmpty(request.Header) ? "Message from Server" : request.Header,
- TimeoutMs = request.TimeoutMs,
- Text = request.Text
- };
-
- return _sessionManager.SendMessageCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(Play request)
- {
- return _sessionManager.SendPlayCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
- }
-
- public Task Post(SendGeneralCommand request)
- {
- var currentSession = GetSession(_sessionContext);
-
- var command = new GeneralCommand
- {
- Name = request.Command,
- ControllingUserId = currentSession.UserId
- };
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
- }
-
- public Task Post(SendFullGeneralCommand request)
- {
- var currentSession = GetSession(_sessionContext);
-
- request.ControllingUserId = currentSession.UserId;
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None);
- }
-
- public void Post(AddUserToSession request)
- {
- _sessionManager.AddAdditionalUser(request.Id, new Guid(request.UserId));
- }
-
- public void Delete(RemoveUserFromSession request)
- {
- _sessionManager.RemoveAdditionalUser(request.Id, new Guid(request.UserId));
- }
-
- public void Post(PostCapabilities request)
- {
- if (string.IsNullOrWhiteSpace(request.Id))
- {
- request.Id = GetSession(_sessionContext).Id;
- }
-
- _sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
- {
- PlayableMediaTypes = SplitValue(request.PlayableMediaTypes, ','),
- SupportedCommands = SplitValue(request.SupportedCommands, ','),
- SupportsMediaControl = request.SupportsMediaControl,
- SupportsSync = request.SupportsSync,
- SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
- });
- }
-
- public void Post(PostFullCapabilities request)
- {
- if (string.IsNullOrWhiteSpace(request.Id))
- {
- request.Id = GetSession(_sessionContext).Id;
- }
-
- _sessionManager.ReportCapabilities(request.Id, request);
- }
-
- public void Post(ReportViewing request)
- {
- request.SessionId = GetSession(_sessionContext).Id;
-
- _sessionManager.ReportNowViewingItem(request.SessionId, request.ItemId);
- }
- }
-}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
deleted file mode 100644
index a70da8e56..000000000
--- 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
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")]
- public int Index { get; set; }
- }
-
- [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
- [Authenticated]
- public class SearchRemoteSubtitles : IReturn<RemoteSubtitleInfo[]>
- {
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Language { get; set; }
-
- public bool? IsPerfectMatch { get; set; }
- }
-
- [Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")]
- [Authenticated]
- public class DownloadRemoteSubtitles : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SubtitleId { get; set; }
- }
-
- [Route("/Providers/Subtitles/Subtitles/{Id}", "GET")]
- [Authenticated]
- public class GetRemoteSubtitles : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
- [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/{StartPositionTicks}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
- public class GetSubtitle
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string MediaSourceId { get; set; }
-
- [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
- public int Index { get; set; }
-
- [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Format { get; set; }
-
- [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public long StartPositionTicks { get; set; }
-
- [ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public long? EndPositionTicks { get; set; }
-
- [ApiMember(Name = "CopyTimestamps", Description = "CopyTimestamps", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool CopyTimestamps { get; set; }
-
- public bool AddVttTimeMap { get; set; }
- }
-
- [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
- [Authenticated]
- public class GetSubtitlePlaylist
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string MediaSourceId { get; set; }
-
- [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
- public int Index { get; set; }
-
- [ApiMember(Name = "SegmentLength", Description = "The subtitle srgment length", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int SegmentLength { get; set; }
- }
-
- public class SubtitleService : BaseApiService
- {
- private readonly ILibraryManager _libraryManager;
- private readonly ISubtitleManager _subtitleManager;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IMediaSourceManager _mediaSourceManager;
- private readonly IProviderManager _providerManager;
- private readonly IFileSystem _fileSystem;
- private readonly IAuthorizationContext _authContext;
-
- public SubtitleService(
- ILogger<SubtitleService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ILibraryManager libraryManager,
- ISubtitleManager subtitleManager,
- ISubtitleEncoder subtitleEncoder,
- IMediaSourceManager mediaSourceManager,
- IProviderManager providerManager,
- IFileSystem fileSystem,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _libraryManager = libraryManager;
- _subtitleManager = subtitleManager;
- _subtitleEncoder = subtitleEncoder;
- _mediaSourceManager = mediaSourceManager;
- _providerManager = providerManager;
- _fileSystem = fileSystem;
- _authContext = authContext;
- }
-
- public async Task<object> Get(GetSubtitlePlaylist request)
- {
- var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
-
- var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false);
-
- var builder = new StringBuilder();
-
- var runtime = mediaSource.RunTimeTicks ?? -1;
-
- if (runtime <= 0)
- {
- throw new ArgumentException("HLS Subtitles are not supported for this media.");
- }
-
- var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
- if (segmentLengthTicks <= 0)
- {
- throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)");
- }
-
- builder.AppendLine("#EXTM3U");
- builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture));
- builder.AppendLine("#EXT-X-VERSION:3");
- builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
- builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-
- long positionTicks = 0;
-
- var accessToken = _authContext.GetAuthorizationInfo(Request).Token;
-
- while (positionTicks < runtime)
- {
- var remaining = runtime - positionTicks;
- var lengthTicks = Math.Min(remaining, segmentLengthTicks);
-
- builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture) + ",");
-
- var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
-
- var url = string.Format("stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
- positionTicks.ToString(CultureInfo.InvariantCulture),
- endPositionTicks.ToString(CultureInfo.InvariantCulture),
- accessToken);
-
- builder.AppendLine(url);
-
- positionTicks += segmentLengthTicks;
- }
-
- builder.AppendLine("#EXT-X-ENDLIST");
-
- return ResultFactory.GetResult(Request, builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
- }
-
- public async Task<object> Get(GetSubtitle request)
- {
- if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
- {
- request.Format = "json";
- }
-
- if (string.IsNullOrEmpty(request.Format))
- {
- var item = (Video)_libraryManager.GetItemById(request.Id);
-
- var idString = request.Id.ToString("N", CultureInfo.InvariantCulture);
- var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null)
- .First(i => string.Equals(i.Id, request.MediaSourceId ?? idString));
-
- var subtitleStream = mediaSource.MediaStreams
- .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index);
-
- return await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false);
- }
-
- if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
- {
- using var stream = await GetSubtitles(request).ConfigureAwait(false);
- using var reader = new StreamReader(stream);
-
- var text = reader.ReadToEnd();
-
- text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
-
- return ResultFactory.GetResult(Request, text, MimeTypes.GetMimeType("file." + request.Format));
- }
-
- return ResultFactory.GetResult(Request, await GetSubtitles(request).ConfigureAwait(false), MimeTypes.GetMimeType("file." + request.Format));
- }
-
- private Task<Stream> GetSubtitles(GetSubtitle request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- return _subtitleEncoder.GetSubtitles(item,
- request.MediaSourceId,
- request.Index,
- request.Format,
- request.StartPositionTicks,
- request.EndPositionTicks ?? 0,
- request.CopyTimestamps,
- CancellationToken.None);
- }
-
- public async Task<object> Get(SearchRemoteSubtitles request)
- {
- var video = (Video)_libraryManager.GetItemById(request.Id);
-
- return await _subtitleManager.SearchSubtitles(video, request.Language, request.IsPerfectMatch, CancellationToken.None).ConfigureAwait(false);
- }
-
- public Task Delete(DeleteSubtitle request)
- {
- var item = _libraryManager.GetItemById(request.Id);
- return _subtitleManager.DeleteSubtitles(item, request.Index);
- }
-
- public async Task<object> Get(GetRemoteSubtitles request)
- {
- var result = await _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).ConfigureAwait(false);
-
- return ResultFactory.GetResult(Request, result.Stream, MimeTypes.GetMimeType("file." + result.Format));
- }
-
- public void Post(DownloadRemoteSubtitles request)
- {
- var video = (Video)_libraryManager.GetItemById(request.Id);
-
- Task.Run(async () =>
- {
- try
- {
- await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
- .ConfigureAwait(false);
-
- _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, "Error downloading subtitles");
- }
- });
- }
- }
-}
diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs
deleted file mode 100644
index 17afa8e79..000000000
--- 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<QueryResult<BaseItemDto>>
- {
- public string MediaType { get; set; }
-
- public string Type { get; set; }
-
- public Guid UserId { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- public int? StartIndex { get; set; }
-
- public int? Limit { get; set; }
-
- public string[] GetMediaTypes()
- {
- return (MediaType ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetIncludeItemTypes()
- {
- return (Type ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-
- public class SuggestionsService : BaseApiService
- {
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
-
- public SuggestionsService(
- ILogger<SuggestionsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IDtoService dtoService,
- IAuthorizationContext authContext,
- IUserManager userManager,
- ILibraryManager libraryManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _dtoService = dtoService;
- _authContext = authContext;
- _userManager = userManager;
- _libraryManager = libraryManager;
- }
-
- public object Get(GetSuggestedItems request)
- {
- return GetResultItems(request);
- }
-
- private QueryResult<BaseItemDto> GetResultItems(GetSuggestedItems request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var dtoOptions = GetDtoOptions(_authContext, request);
- var result = GetItems(request, user, dtoOptions);
-
- var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = dtoList
- };
- }
-
- private QueryResult<BaseItem> GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions)
- {
- return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
- {
- OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
- MediaTypes = request.GetMediaTypes(),
- IncludeItemTypes = request.GetIncludeItemTypes(),
- IsVirtualItem = false,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- DtoOptions = dtoOptions,
- EnableTotalRecordCount = request.EnableTotalRecordCount,
- Recursive = true
- });
- }
- }
-}
diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs
deleted file mode 100644
index 4afa6e114..000000000
--- 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<QueryResult<ActivityLogEntry>>
- {
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MinDate { get; set; }
-
- public bool? HasUserId { get; set; }
- }
-
- [Authenticated(Roles = "Admin")]
- public class ActivityLogService : BaseApiService
- {
- private readonly IActivityManager _activityManager;
-
- public ActivityLogService(
- ILogger<ActivityLogService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IActivityManager activityManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _activityManager = activityManager;
- }
-
- public object Get(GetActivityLogs request)
- {
- DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
- (DateTime?)null :
- DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-
- var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
- entries => entries.Where(entry => entry.DateCreated >= minDate
- && (!request.HasUserId.HasValue || (request.HasUserId.Value
- ? entry.UserId != Guid.Empty
- : entry.UserId == Guid.Empty))));
-
- var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit);
-
- return ToOptimizedResult(result);
- }
- }
-}
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
deleted file mode 100644
index e0e20d828..000000000
--- 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
-{
- /// <summary>
- /// Class GetSystemInfo.
- /// </summary>
- [Route("/System/Info", "GET", Summary = "Gets information about the server")]
- [Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)]
- public class GetSystemInfo : IReturn<SystemInfo>
- {
- }
-
- [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")]
- public class GetPublicSystemInfo : IReturn<PublicSystemInfo>
- {
- }
-
- [Route("/System/Ping", "POST")]
- [Route("/System/Ping", "GET")]
- public class PingSystem : IReturnVoid
- {
- }
-
- /// <summary>
- /// Class RestartApplication.
- /// </summary>
- [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
- [Authenticated(Roles = "Admin", AllowLocal = true)]
- public class RestartApplication
- {
- }
-
- /// <summary>
- /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server.
- /// </summary>
- [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")]
- [Authenticated(Roles = "Admin", AllowLocal = true)]
- public class ShutdownApplication
- {
- }
-
- [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
- [Authenticated(Roles = "Admin")]
- public class GetServerLogs : IReturn<LogFile[]>
- {
- }
-
- [Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
- [Authenticated]
- public class GetEndpointInfo : IReturn<EndPointInfo>
- {
- public string Endpoint { get; set; }
- }
-
- [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")]
- [Authenticated(Roles = "Admin")]
- public class GetLogFile
- {
- [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Name { get; set; }
- }
-
- [Route("/System/WakeOnLanInfo", "GET", Summary = "Gets wake on lan information")]
- [Authenticated]
- public class GetWakeOnLanInfo : IReturn<WakeOnLanInfo[]>
- {
- }
-
- /// <summary>
- /// Class SystemInfoService.
- /// </summary>
- public class SystemService : BaseApiService
- {
- /// <summary>
- /// The _app host.
- /// </summary>
- private readonly IServerApplicationHost _appHost;
- private readonly IApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
-
- private readonly INetworkManager _network;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SystemService" /> class.
- /// </summary>
- /// <param name="appHost">The app host.</param>
- /// <param name="fileSystem">The file system.</param>
- /// <exception cref="ArgumentNullException">jsonSerializer</exception>
- public SystemService(
- ILogger<SystemService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IServerApplicationHost appHost,
- IFileSystem fileSystem,
- INetworkManager network)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _appPaths = serverConfigurationManager.ApplicationPaths;
- _appHost = appHost;
- _fileSystem = fileSystem;
- _network = network;
- }
-
- public object Post(PingSystem request)
- {
- return _appHost.Name;
- }
-
- public object Get(GetWakeOnLanInfo request)
- {
- var result = _appHost.GetWakeOnLanInfo();
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetServerLogs request)
- {
- IEnumerable<FileSystemMetadata> files;
-
- try
- {
- files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false);
- }
- catch (IOException ex)
- {
- Logger.LogError(ex, "Error getting logs");
- files = Enumerable.Empty<FileSystemMetadata>();
- }
-
- var result = files.Select(i => new LogFile
- {
- DateCreated = _fileSystem.GetCreationTimeUtc(i),
- DateModified = _fileSystem.GetLastWriteTimeUtc(i),
- Name = i.Name,
- Size = i.Length
- }).OrderByDescending(i => i.DateModified)
- .ThenByDescending(i => i.DateCreated)
- .ThenBy(i => i.Name)
- .ToArray();
-
- return ToOptimizedResult(result);
- }
-
- public Task<object> Get(GetLogFile request)
- {
- var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
- .First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
-
- // For older files, assume fully static
- var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite;
-
- return ResultFactory.GetStaticFileResult(Request, file.FullName, fileShare);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Get(GetSystemInfo request)
- {
- var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Get(GetPublicSystemInfo request)
- {
- var result = await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(RestartApplication request)
- {
- _appHost.Restart();
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(ShutdownApplication request)
- {
- Task.Run(async () =>
- {
- await Task.Delay(100).ConfigureAwait(false);
- await _appHost.Shutdown().ConfigureAwait(false);
- });
- }
-
- public object Get(GetEndpointInfo request)
- {
- return ToOptimizedResult(new EndPointInfo
- {
- IsLocal = Request.IsLocal,
- IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
- });
- }
- }
-}
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
deleted file mode 100644
index 165abd613..000000000
--- 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
-{
- /// <summary>
- /// Class GetNextUpEpisodes.
- /// </summary>
- [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")]
- public class GetNextUpEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SeriesId { get; set; }
-
- /// <summary>
- /// Specify this to localize the search to a specific item or folder. Omit to use the root.
- /// </summary>
- /// <value>The parent id.</value>
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- public GetNextUpEpisodes()
- {
- EnableTotalRecordCount = true;
- }
- }
-
- [Route("/Shows/Upcoming", "GET", Summary = "Gets a list of upcoming episodes")]
- public class GetUpcomingEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- /// <summary>
- /// Specify this to localize the search to a specific item or folder. Omit to use the root.
- /// </summary>
- /// <value>The parent id.</value>
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
- }
-
- [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")]
- public class GetEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public int? Season { get; set; }
-
- [ApiMember(Name = "SeasonId", Description = "Optional. Filter by season id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SeasonId { get; set; }
-
- [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsMissing { get; set; }
-
- [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string AdjacentTo { get; set; }
-
- [ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string StartItemId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string SortBy { get; set; }
-
- [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public SortOrder? SortOrder { get; set; }
- }
-
- [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")]
- public class GetSeasons : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsSpecialSeason { get; set; }
-
- [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsMissing { get; set; }
-
- [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string AdjacentTo { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
- }
-
- /// <summary>
- /// Class TvShowsService.
- /// </summary>
- [Authenticated]
- public class TvShowsService : BaseApiService
- {
- /// <summary>
- /// The _user manager.
- /// </summary>
- private readonly IUserManager _userManager;
-
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
-
- private readonly IDtoService _dtoService;
- private readonly ITVSeriesManager _tvSeriesManager;
- private readonly IAuthorizationContext _authContext;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="TvShowsService" /> class.
- /// </summary>
- /// <param name="userManager">The user manager.</param>
- /// <param name="userDataManager">The user data repository.</param>
- /// <param name="libraryManager">The library manager.</param>
- public TvShowsService(
- ILogger<TvShowsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- ITVSeriesManager tvSeriesManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _tvSeriesManager = tvSeriesManager;
- _authContext = authContext;
- }
-
- public object Get(GetUpcomingEpisodes request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1);
-
- var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
-
- var options = GetDtoOptions(_authContext, request);
-
- var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { typeof(Episode).Name },
- OrderBy = new[] { ItemSortBy.PremiereDate, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
- MinPremiereDate = minPremiereDate,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- ParentId = parentIdGuid,
- Recursive = true,
- DtoOptions = options
- });
-
- var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = itemsResult.Count,
- Items = returnItems
- };
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetNextUpEpisodes request)
- {
- var options = GetDtoOptions(_authContext, request);
-
- var result = _tvSeriesManager.GetNextUp(new NextUpQuery
- {
- Limit = request.Limit,
- ParentId = request.ParentId,
- SeriesId = request.SeriesId,
- StartIndex = request.StartIndex,
- UserId = request.UserId,
- EnableTotalRecordCount = request.EnableTotalRecordCount
- }, options);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user);
-
- return ToOptimizedResult(new QueryResult<BaseItemDto>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = returnItems
- });
- }
-
- /// <summary>
- /// Applies the paging.
- /// </summary>
- /// <param name="items">The items.</param>
- /// <param name="startIndex">The start index.</param>
- /// <param name="limit">The limit.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- private IEnumerable<BaseItem> ApplyPaging(IEnumerable<BaseItem> items, int? startIndex, int? limit)
- {
- // Start at
- if (startIndex.HasValue)
- {
- items = items.Skip(startIndex.Value);
- }
-
- // Return limit
- if (limit.HasValue)
- {
- items = items.Take(limit.Value);
- }
-
- return items;
- }
-
- public object Get(GetSeasons request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var series = GetSeries(request.Id);
-
- if (series == null)
- {
- throw new ResourceNotFoundException("Series not found");
- }
-
- var seasons = series.GetItemList(new InternalItemsQuery(user)
- {
- IsMissing = request.IsMissing,
- IsSpecialSeason = request.IsSpecialSeason,
- AdjacentTo = request.AdjacentTo
- });
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = returnItems.Count,
- Items = returnItems
- };
- }
-
- private Series GetSeries(string seriesId)
- {
- if (!string.IsNullOrWhiteSpace(seriesId))
- {
- return _libraryManager.GetItemById(seriesId) as Series;
- }
-
- return null;
- }
-
- public object Get(GetEpisodes request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- List<BaseItem> episodes;
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- if (!string.IsNullOrWhiteSpace(request.SeasonId))
- {
- if (!(_libraryManager.GetItemById(new Guid(request.SeasonId)) is Season season))
- {
- throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId);
- }
-
- episodes = season.GetEpisodes(user, dtoOptions);
- }
- else if (request.Season.HasValue)
- {
- var series = GetSeries(request.Id);
-
- if (series == null)
- {
- throw new ResourceNotFoundException("Series not found");
- }
-
- var season = series.GetSeasons(user, dtoOptions).FirstOrDefault(i => i.IndexNumber == request.Season.Value);
-
- episodes = season == null ? new List<BaseItem>() : ((Season)season).GetEpisodes(user, dtoOptions);
- }
- else
- {
- var series = GetSeries(request.Id);
-
- if (series == null)
- {
- throw new ResourceNotFoundException("Series not found");
- }
-
- episodes = series.GetEpisodes(user, dtoOptions).ToList();
- }
-
- // Filter after the fact in case the ui doesn't want them
- if (request.IsMissing.HasValue)
- {
- var val = request.IsMissing.Value;
- episodes = episodes.Where(i => ((Episode)i).IsMissingEpisode == val).ToList();
- }
-
- if (!string.IsNullOrWhiteSpace(request.StartItemId))
- {
- episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N", CultureInfo.InvariantCulture), request.StartItemId, StringComparison.OrdinalIgnoreCase)).ToList();
- }
-
- // This must be the last filter
- if (!string.IsNullOrEmpty(request.AdjacentTo))
- {
- episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo).ToList();
- }
-
- if (string.Equals(request.SortBy, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
- {
- episodes.Shuffle();
- }
-
- var returnItems = episodes;
-
- if (request.StartIndex.HasValue || request.Limit.HasValue)
- {
- returnItems = ApplyPaging(episodes, request.StartIndex, request.Limit).ToList();
- }
-
- var dtos = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = episodes.Count,
- Items = dtos
- };
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
deleted file mode 100644
index 9875e0208..000000000
--- 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
-{
- /// <summary>
- /// Class GetArtists.
- /// </summary>
- [Route("/Artists", "GET", Summary = "Gets all artists from a given item, folder, or the entire library")]
- public class GetArtists : GetItemsByName
- {
- }
-
- [Route("/Artists/AlbumArtists", "GET", Summary = "Gets all album artists from a given item, folder, or the entire library")]
- public class GetAlbumArtists : GetItemsByName
- {
- }
-
- [Route("/Artists/{Name}", "GET", Summary = "Gets an artist, by name")]
- public class GetArtist : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class ArtistsService.
- /// </summary>
- [Authenticated]
- public class ArtistsService : BaseItemsByNameService<MusicArtist>
- {
- public ArtistsService(
- ILogger<ArtistsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- userDataRepository,
- dtoService,
- authorizationContext)
- {
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetArtist request)
- {
- return GetItem(request);
- }
-
- /// <summary>
- /// Gets the item.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- private BaseItemDto GetItem(GetArtist request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- var item = GetArtist(request.Name, LibraryManager, dtoOptions);
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
-
- return DtoService.GetBaseItemDto(item, dtoOptions, user);
- }
-
- return DtoService.GetBaseItemDto(item, dtoOptions);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetArtists request)
- {
- return GetResultSlim(request);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetAlbumArtists request)
- {
- var result = GetResultSlim(request);
-
- return ToOptimizedResult(result);
- }
-
- protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- return request is GetAlbumArtists ? LibraryManager.GetAlbumArtists(query) : LibraryManager.GetArtists(query);
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
- protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
deleted file mode 100644
index fd639caf1..000000000
--- 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
-{
- /// <summary>
- /// Class BaseItemsByNameService.
- /// </summary>
- /// <typeparam name="TItemType">The type of the T item type.</typeparam>
- public abstract class BaseItemsByNameService<TItemType> : BaseApiService
- where TItemType : BaseItem, IItemByName
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="BaseItemsByNameService{TItemType}" /> class.
- /// </summary>
- /// <param name="userManager">The user manager.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="userDataRepository">The user data repository.</param>
- /// <param name="dtoService">The dto service.</param>
- protected BaseItemsByNameService(
- ILogger<BaseItemsByNameService<TItemType>> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- UserManager = userManager;
- LibraryManager = libraryManager;
- UserDataRepository = userDataRepository;
- DtoService = dtoService;
- AuthorizationContext = authorizationContext;
- }
-
- /// <summary>
- /// Gets the _user manager.
- /// </summary>
- protected IUserManager UserManager { get; }
-
- /// <summary>
- /// Gets the library manager.
- /// </summary>
- protected ILibraryManager LibraryManager { get; }
-
- protected IUserDataManager UserDataRepository { get; }
-
- protected IDtoService DtoService { get; }
-
- protected IAuthorizationContext AuthorizationContext { get; }
-
- protected BaseItem GetParentItem(GetItemsByName request)
- {
- BaseItem parentItem;
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
- }
- else
- {
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
- }
-
- return parentItem;
- }
-
- protected string GetParentItemViewType(GetItemsByName request)
- {
- var parent = GetParentItem(request);
-
- if (parent is IHasCollectionType collectionFolder)
- {
- return collectionFolder.CollectionType;
- }
-
- return null;
- }
-
- protected QueryResult<BaseItemDto> GetResultSlim(GetItemsByName request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- User user = null;
- BaseItem parentItem;
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- user = UserManager.GetUserById(request.UserId);
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
- }
- else
- {
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
- }
-
- var excludeItemTypes = request.GetExcludeItemTypes();
- var includeItemTypes = request.GetIncludeItemTypes();
- var mediaTypes = request.GetMediaTypes();
-
- var query = new InternalItemsQuery(user)
- {
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
- MediaTypes = mediaTypes,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- IsFavorite = request.IsFavorite,
- NameLessThan = request.NameLessThan,
- NameStartsWith = request.NameStartsWith,
- NameStartsWithOrGreater = request.NameStartsWithOrGreater,
- Tags = request.GetTags(),
- OfficialRatings = request.GetOfficialRatings(),
- Genres = request.GetGenres(),
- GenreIds = GetGuids(request.GenreIds),
- StudioIds = GetGuids(request.StudioIds),
- Person = request.Person,
- PersonIds = GetGuids(request.PersonIds),
- PersonTypes = request.GetPersonTypes(),
- Years = request.GetYears(),
- MinCommunityRating = request.MinCommunityRating,
- DtoOptions = dtoOptions,
- SearchTerm = request.SearchTerm,
- EnableTotalRecordCount = request.EnableTotalRecordCount
- };
-
- if (!string.IsNullOrWhiteSpace(request.ParentId))
- {
- if (parentItem is Folder)
- {
- query.AncestorIds = new[] { new Guid(request.ParentId) };
- }
- else
- {
- query.ItemIds = new[] { new Guid(request.ParentId) };
- }
- }
-
- // Studios
- if (!string.IsNullOrEmpty(request.Studios))
- {
- query.StudioIds = request.Studios.Split('|').Select(i =>
- {
- try
- {
- return LibraryManager.GetStudio(i);
- }
- catch
- {
- return null;
- }
- }).Where(i => i != null).Select(i => i.Id).ToArray();
- }
-
- foreach (var filter in request.GetFilters())
- {
- switch (filter)
- {
- case ItemFilter.Dislikes:
- query.IsLiked = false;
- break;
- case ItemFilter.IsFavorite:
- query.IsFavorite = true;
- break;
- case ItemFilter.IsFavoriteOrLikes:
- query.IsFavoriteOrLiked = true;
- break;
- case ItemFilter.IsFolder:
- query.IsFolder = true;
- break;
- case ItemFilter.IsNotFolder:
- query.IsFolder = false;
- break;
- case ItemFilter.IsPlayed:
- query.IsPlayed = true;
- break;
- case ItemFilter.IsResumable:
- query.IsResumable = true;
- break;
- case ItemFilter.IsUnplayed:
- query.IsPlayed = false;
- break;
- case ItemFilter.Likes:
- query.IsLiked = true;
- break;
- }
- }
-
- var result = GetItems(request, query);
-
- var dtos = result.Items.Select(i =>
- {
- var dto = DtoService.GetItemByNameDto(i.Item1, dtoOptions, null, user);
-
- if (!string.IsNullOrWhiteSpace(request.IncludeItemTypes))
- {
- SetItemCounts(dto, i.Item2);
- }
-
- return dto;
- });
-
- return new QueryResult<BaseItemDto>
- {
- Items = dtos.ToArray(),
- TotalRecordCount = result.TotalRecordCount
- };
- }
-
- protected virtual QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- return new QueryResult<(BaseItem, ItemCounts)>();
- }
-
- private void SetItemCounts(BaseItemDto dto, ItemCounts counts)
- {
- dto.ChildCount = counts.ItemCount;
- dto.ProgramCount = counts.ProgramCount;
- dto.SeriesCount = counts.SeriesCount;
- dto.EpisodeCount = counts.EpisodeCount;
- dto.MovieCount = counts.MovieCount;
- dto.TrailerCount = counts.TrailerCount;
- dto.AlbumCount = counts.AlbumCount;
- dto.SongCount = counts.SongCount;
- dto.ArtistCount = counts.ArtistCount;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{ItemsResult}.</returns>
- protected QueryResult<BaseItemDto> GetResult(GetItemsByName request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- User user = null;
- BaseItem parentItem;
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- user = UserManager.GetUserById(request.UserId);
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
- }
- else
- {
- parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
- }
-
- IList<BaseItem> items;
-
- var excludeItemTypes = request.GetExcludeItemTypes();
- var includeItemTypes = request.GetIncludeItemTypes();
- var mediaTypes = request.GetMediaTypes();
-
- var query = new InternalItemsQuery(user)
- {
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
- MediaTypes = mediaTypes,
- DtoOptions = dtoOptions
- };
-
- bool Filter(BaseItem i) => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes);
-
- if (parentItem.IsFolder)
- {
- var folder = (Folder)parentItem;
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- items = request.Recursive ?
- folder.GetRecursiveChildren(user, query).ToList() :
- folder.GetChildren(user, true).Where(Filter).ToList();
- }
- else
- {
- items = request.Recursive ?
- folder.GetRecursiveChildren(Filter) :
- folder.Children.Where(Filter).ToList();
- }
- }
- else
- {
- items = new[] { parentItem }.Where(Filter).ToList();
- }
-
- var extractedItems = GetAllItems(request, items);
-
- var filteredItems = LibraryManager.Sort(extractedItems, user, request.GetOrderBy());
-
- var ibnItemsArray = filteredItems.ToList();
-
- IEnumerable<BaseItem> ibnItems = ibnItemsArray;
-
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = ibnItemsArray.Count
- };
-
- if (request.StartIndex.HasValue || request.Limit.HasValue)
- {
- if (request.StartIndex.HasValue)
- {
- ibnItems = ibnItems.Skip(request.StartIndex.Value);
- }
-
- if (request.Limit.HasValue)
- {
- ibnItems = ibnItems.Take(request.Limit.Value);
- }
- }
-
- var tuples = ibnItems.Select(i => new Tuple<BaseItem, List<BaseItem>>(i, new List<BaseItem>()));
-
- var dtos = tuples.Select(i => DtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user));
-
- result.Items = dtos.Where(i => i != null).ToArray();
-
- return result;
- }
-
- /// <summary>
- /// Filters the items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="f">The f.</param>
- /// <param name="excludeItemTypes">The exclude item types.</param>
- /// <param name="includeItemTypes">The include item types.</param>
- /// <param name="mediaTypes">The media types.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- private bool FilterItem(GetItemsByName request, BaseItem f, string[] excludeItemTypes, string[] includeItemTypes, string[] mediaTypes)
- {
- // Exclude item types
- if (excludeItemTypes.Length > 0 && excludeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
-
- // Include item types
- if (includeItemTypes.Length > 0 && !includeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
-
- // Include MediaTypes
- if (mediaTypes.Length > 0 && !mediaTypes.Contains(f.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
-
- return true;
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Task{`0}}.</returns>
- protected abstract IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items);
- }
-
- /// <summary>
- /// Class GetItemsByName.
- /// </summary>
- public class GetItemsByName : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
- {
- public GetItemsByName()
- {
- Recursive = true;
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
deleted file mode 100644
index 344861a49..000000000
--- 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;
- }
-
- /// <summary>
- /// Gets or sets the max offical rating.
- /// </summary>
- /// <value>The max offical rating.</value>
- [ApiMember(Name = "MaxOfficialRating", Description = "Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MaxOfficialRating { get; set; }
-
- [ApiMember(Name = "HasThemeSong", Description = "Optional filter by items with theme songs.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasThemeSong { get; set; }
-
- [ApiMember(Name = "HasThemeVideo", Description = "Optional filter by items with theme videos.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasThemeVideo { get; set; }
-
- [ApiMember(Name = "HasSubtitles", Description = "Optional filter by items with subtitles.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasSubtitles { get; set; }
-
- [ApiMember(Name = "HasSpecialFeature", Description = "Optional filter by items with special features.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasSpecialFeature { get; set; }
-
- [ApiMember(Name = "HasTrailer", Description = "Optional filter by items with trailers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasTrailer { get; set; }
-
- [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string AdjacentTo { get; set; }
-
- [ApiMember(Name = "MinIndexNumber", Description = "Optional filter by minimum index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? MinIndexNumber { get; set; }
-
- [ApiMember(Name = "ParentIndexNumber", Description = "Optional filter by parent index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ParentIndexNumber { get; set; }
-
- [ApiMember(Name = "HasParentalRating", Description = "Optional filter by items that have or do not have a parental rating", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasParentalRating { get; set; }
-
- [ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsHD { get; set; }
-
- public bool? Is4K { get; set; }
-
- [ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string LocationTypes { get; set; }
-
- [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeLocationTypes { get; set; }
-
- [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsMissing { get; set; }
-
- [ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsUnaired { get; set; }
-
- [ApiMember(Name = "MinCommunityRating", Description = "Optional filter by minimum community rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public double? MinCommunityRating { get; set; }
-
- [ApiMember(Name = "MinCriticRating", Description = "Optional filter by minimum critic rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public double? MinCriticRating { get; set; }
-
- [ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? AiredDuringSeason { get; set; }
-
- [ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MinPremiereDate { get; set; }
-
- [ApiMember(Name = "MinDateLastSaved", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MinDateLastSaved { get; set; }
-
- [ApiMember(Name = "MinDateLastSavedForUser", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MinDateLastSavedForUser { get; set; }
-
- [ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MaxPremiereDate { get; set; }
-
- [ApiMember(Name = "HasOverview", Description = "Optional filter by items that have an overview or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasOverview { get; set; }
-
- [ApiMember(Name = "HasImdbId", Description = "Optional filter by items that have an imdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasImdbId { get; set; }
-
- [ApiMember(Name = "HasTmdbId", Description = "Optional filter by items that have a tmdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasTmdbId { get; set; }
-
- [ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? HasTvdbId { get; set; }
-
- [ApiMember(Name = "ExcludeItemIds", Description = "Optional. If specified, results will be filtered by exxcluding item ids. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeItemIds { get; set; }
-
- public bool EnableTotalRecordCount { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return.
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Whether or not to perform the query recursively.
- /// </summary>
- /// <value><c>true</c> if recursive; otherwise, <c>false</c>.</value>
- [ApiMember(Name = "Recursive", Description = "When searching within folders, this determines whether or not the search will be recursive. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool Recursive { get; set; }
-
- public string SearchTerm { get; set; }
-
- /// <summary>
- /// Gets or sets the sort order.
- /// </summary>
- /// <value>The sort order.</value>
- [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string SortOrder { get; set; }
-
- /// <summary>
- /// Specify this to localize the search to a specific item or folder. Omit to use the root.
- /// </summary>
- /// <value>The parent id.</value>
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ParentId { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information.
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- /// <summary>
- /// Gets or sets the exclude item types.
- /// </summary>
- /// <value>The exclude item types.</value>
- [ApiMember(Name = "ExcludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeItemTypes { get; set; }
-
- /// <summary>
- /// Gets or sets the include item types.
- /// </summary>
- /// <value>The include item types.</value>
- [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string IncludeItemTypes { get; set; }
-
- /// <summary>
- /// Filters to apply to the results.
- /// </summary>
- /// <value>The filters.</value>
- [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Filters { get; set; }
-
- /// <summary>
- /// Gets or sets the Isfavorite option.
- /// </summary>
- /// <value>IsFavorite</value>
- [ApiMember(Name = "IsFavorite", Description = "Optional filter by items that are marked as favorite, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsFavorite { get; set; }
-
- /// <summary>
- /// Gets or sets the media types.
- /// </summary>
- /// <value>The media types.</value>
- [ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string MediaTypes { get; set; }
-
- /// <summary>
- /// Gets or sets the image types.
- /// </summary>
- /// <value>The image types.</value>
- [ApiMember(Name = "ImageTypes", Description = "Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ImageTypes { get; set; }
-
- /// <summary>
- /// What to sort the results by.
- /// </summary>
- /// <value>The sort by.</value>
- [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string SortBy { get; set; }
-
- [ApiMember(Name = "IsPlayed", Description = "Optional filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsPlayed { get; set; }
-
- /// <summary>
- /// Limit results to items containing specific genres.
- /// </summary>
- /// <value>The genres.</value>
- [ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Genres { get; set; }
-
- public string GenreIds { get; set; }
-
- [ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string OfficialRatings { get; set; }
-
- [ApiMember(Name = "Tags", Description = "Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Tags { get; set; }
-
- /// <summary>
- /// Limit results to items containing specific years.
- /// </summary>
- /// <value>The years.</value>
- [ApiMember(Name = "Years", Description = "Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Years { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- /// <summary>
- /// Limit results to items containing a specific person.
- /// </summary>
- /// <value>The person.</value>
- [ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Person { get; set; }
-
- [ApiMember(Name = "PersonIds", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string PersonIds { get; set; }
-
- /// <summary>
- /// If the Person filter is used, this can also be used to restrict to a specific person type.
- /// </summary>
- /// <value>The type of the person.</value>
- [ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string PersonTypes { get; set; }
-
- /// <summary>
- /// Limit results to items containing specific studios.
- /// </summary>
- /// <value>The studios.</value>
- [ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Studios { get; set; }
-
- [ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string StudioIds { get; set; }
-
- /// <summary>
- /// Gets or sets the studios.
- /// </summary>
- /// <value>The studios.</value>
- [ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Artists { get; set; }
-
- public string ExcludeArtistIds { get; set; }
-
- [ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ArtistIds { get; set; }
-
- public string AlbumArtistIds { get; set; }
-
- public string ContributingArtistIds { get; set; }
-
- [ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Albums { get; set; }
-
- public string AlbumIds { get; set; }
-
- /// <summary>
- /// Gets or sets the item ids.
- /// </summary>
- /// <value>The item ids.</value>
- [ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Ids { get; set; }
-
- /// <summary>
- /// Gets or sets the video types.
- /// </summary>
- /// <value>The video types.</value>
- [ApiMember(Name = "VideoTypes", Description = "Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string VideoTypes { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the min offical rating.
- /// </summary>
- /// <value>The min offical rating.</value>
- [ApiMember(Name = "MinOfficialRating", Description = "Optional filter by minimum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string MinOfficialRating { get; set; }
-
- [ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? IsLocked { get; set; }
-
- [ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? IsPlaceHolder { get; set; }
-
- [ApiMember(Name = "HasOfficialRating", Description = "Optional filter by items that have official ratings", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasOfficialRating { get; set; }
-
- [ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? CollapseBoxSetItems { get; set; }
-
- public int? MinWidth { get; set; }
-
- public int? MinHeight { get; set; }
-
- public int? MaxWidth { get; set; }
-
- public int? MaxHeight { get; set; }
-
- /// <summary>
- /// Gets or sets the video formats.
- /// </summary>
- /// <value>The video formats.</value>
- [ApiMember(Name = "Is3D", Description = "Optional filter by items that are 3D, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? Is3D { get; set; }
-
- /// <summary>
- /// Gets or sets the series status.
- /// </summary>
- /// <value>The series status.</value>
- [ApiMember(Name = "SeriesStatus", Description = "Optional filter by Series Status. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string SeriesStatus { get; set; }
-
- [ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string NameStartsWithOrGreater { get; set; }
-
- [ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string NameStartsWith { get; set; }
-
- [ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string NameLessThan { get; set; }
-
- public string[] GetGenres()
- {
- return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetTags()
- {
- return (Tags ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetOfficialRatings()
- {
- return (OfficialRatings ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetMediaTypes()
- {
- return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetIncludeItemTypes()
- {
- return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetExcludeItemTypes()
- {
- return (ExcludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public int[] GetYears()
- {
- return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
- }
-
- public string[] GetStudios()
- {
- return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetPersonTypes()
- {
- return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public VideoType[] GetVideoTypes()
- {
- return string.IsNullOrEmpty(VideoTypes)
- ? Array.Empty<VideoType>()
- : VideoTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(v => Enum.Parse<VideoType>(v, true)).ToArray();
- }
-
- /// <summary>
- /// Gets the filters.
- /// </summary>
- /// <returns>IEnumerable{ItemFilter}.</returns>
- public ItemFilter[] GetFilters()
- {
- var val = Filters;
-
- return string.IsNullOrEmpty(val)
- ? Array.Empty<ItemFilter>()
- : val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(v => Enum.Parse<ItemFilter>(v, true)).ToArray();
- }
-
- /// <summary>
- /// Gets the image types.
- /// </summary>
- /// <returns>IEnumerable{ImageType}.</returns>
- public ImageType[] GetImageTypes()
- {
- var val = ImageTypes;
-
- return string.IsNullOrEmpty(val)
- ? Array.Empty<ImageType>()
- : val.Split(',').Select(v => Enum.Parse<ImageType>(v, true)).ToArray();
- }
-
- /// <summary>
- /// Gets the order by.
- /// </summary>
- /// <returns>IEnumerable{ItemSortBy}.</returns>
- public ValueTuple<string, SortOrder>[] GetOrderBy()
- {
- return GetOrderBy(SortBy, SortOrder);
- }
-
- public static ValueTuple<string, SortOrder>[] GetOrderBy(string sortBy, string requestedSortOrder)
- {
- var val = sortBy;
-
- if (string.IsNullOrEmpty(val))
- {
- return Array.Empty<ValueTuple<string, SortOrder>>();
- }
-
- var vals = val.Split(',');
- if (string.IsNullOrWhiteSpace(requestedSortOrder))
- {
- requestedSortOrder = "Ascending";
- }
-
- var sortOrders = requestedSortOrder.Split(',');
-
- var result = new ValueTuple<string, SortOrder>[vals.Length];
-
- for (var i = 0; i < vals.Length; i++)
- {
- var sortOrderIndex = sortOrders.Length > i ? i : 0;
-
- var sortOrderValue = sortOrders.Length > sortOrderIndex ? sortOrders[sortOrderIndex] : null;
- var sortOrder = string.Equals(sortOrderValue, "Descending", StringComparison.OrdinalIgnoreCase)
- ? MediaBrowser.Model.Entities.SortOrder.Descending
- : MediaBrowser.Model.Entities.SortOrder.Ascending;
-
- result[i] = new ValueTuple<string, SortOrder>(vals[i], sortOrder);
- }
-
- return result;
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
deleted file mode 100644
index 7bdfbac98..000000000
--- 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
-{
- /// <summary>
- /// Class GetGenres.
- /// </summary>
- [Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")]
- public class GetGenres : GetItemsByName
- {
- }
-
- /// <summary>
- /// Class GetGenre.
- /// </summary>
- [Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")]
- public class GetGenre : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class GenresService.
- /// </summary>
- [Authenticated]
- public class GenresService : BaseItemsByNameService<Genre>
- {
- public GenresService(
- ILogger<GenresService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- userDataRepository,
- dtoService,
- authorizationContext)
- {
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetGenre request)
- {
- var result = GetItem(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the item.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- private BaseItemDto GetItem(GetGenre request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- var item = GetGenre(request.Name, LibraryManager, dtoOptions);
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
-
- return DtoService.GetBaseItemDto(item, dtoOptions, user);
- }
-
- return DtoService.GetBaseItemDto(item, dtoOptions);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetGenres request)
- {
- var result = GetResultSlim(request);
-
- return ToOptimizedResult(result);
- }
-
- protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- var viewType = GetParentItemViewType(request);
-
- if (string.Equals(viewType, CollectionType.Music) || string.Equals(viewType, CollectionType.MusicVideos))
- {
- return LibraryManager.GetMusicGenres(query);
- }
-
- return LibraryManager.GetGenres(query);
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
- protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
deleted file mode 100644
index 7efe0552c..000000000
--- 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
-{
- /// <summary>
- /// Class GetItems.
- /// </summary>
- [Route("/Items", "GET", Summary = "Gets items based on a query.")]
- [Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
- public class GetItems : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
- {
- }
-
- [Route("/Users/{UserId}/Items/Resume", "GET", Summary = "Gets items based on a query.")]
- public class GetResumeItems : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
- {
- }
-
- /// <summary>
- /// Class ItemsService.
- /// </summary>
- [Authenticated]
- public class ItemsService : BaseApiService
- {
- /// <summary>
- /// The _user manager.
- /// </summary>
- private readonly IUserManager _userManager;
-
- /// <summary>
- /// The _library manager.
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly ILocalizationManager _localization;
-
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ItemsService" /> class.
- /// </summary>
- /// <param name="userManager">The user manager.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="localization">The localization.</param>
- /// <param name="dtoService">The dto service.</param>
- public ItemsService(
- ILogger<ItemsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- ILocalizationManager localization,
- IDtoService dtoService,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _localization = localization;
- _dtoService = dtoService;
- _authContext = authContext;
- }
-
- public object Get(GetResumeItems request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
-
- var options = GetDtoOptions(_authContext, request);
-
- var ancestorIds = Array.Empty<Guid>();
-
- var excludeFolderIds = user.GetPreference(PreferenceKind.LatestItemExcludes);
- if (parentIdGuid.Equals(Guid.Empty) && excludeFolderIds.Length > 0)
- {
- ancestorIds = _libraryManager.GetUserRootFolder().GetChildren(user, true)
- .Where(i => i is Folder)
- .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
- .Select(i => i.Id)
- .ToArray();
- }
-
- var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
- {
- OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) },
- IsResumable = true,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- ParentId = parentIdGuid,
- Recursive = true,
- DtoOptions = options,
- MediaTypes = request.GetMediaTypes(),
- IsVirtualItem = false,
- CollapseBoxSetItems = false,
- EnableTotalRecordCount = request.EnableTotalRecordCount,
- AncestorIds = ancestorIds,
- IncludeItemTypes = request.GetIncludeItemTypes(),
- ExcludeItemTypes = request.GetExcludeItemTypes(),
- SearchTerm = request.SearchTerm
- });
-
- var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- StartIndex = request.StartIndex.GetValueOrDefault(),
- TotalRecordCount = itemsResult.TotalRecordCount,
- Items = returnItems
- };
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetItems request)
- {
- if (request == null)
- {
- throw new ArgumentNullException(nameof(request));
- }
-
- var result = GetItems(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the items.
- /// </summary>
- /// <param name="request">The request.</param>
- private QueryResult<BaseItemDto> GetItems(GetItems request)
- {
- var user = request.UserId == Guid.Empty ? null : _userManager.GetUserById(request.UserId);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = GetQueryResult(request, dtoOptions, user);
-
- if (result == null)
- {
- throw new InvalidOperationException("GetItemsToSerialize returned null");
- }
-
- if (result.Items == null)
- {
- throw new InvalidOperationException("GetItemsToSerialize result.Items returned null");
- }
-
- var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- StartIndex = request.StartIndex.GetValueOrDefault(),
- TotalRecordCount = result.TotalRecordCount,
- Items = dtoList
- };
- }
-
- /// <summary>
- /// Gets the items to serialize.
- /// </summary>
- private QueryResult<BaseItem> GetQueryResult(GetItems request, DtoOptions dtoOptions, User user)
- {
- if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase)
- || string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
- {
- request.ParentId = null;
- }
-
- BaseItem item = null;
-
- if (!string.IsNullOrEmpty(request.ParentId))
- {
- item = _libraryManager.GetItemById(request.ParentId);
- }
-
- if (item == null)
- {
- item = _libraryManager.GetUserRootFolder();
- }
-
- if (!(item is Folder folder))
- {
- folder = _libraryManager.GetUserRootFolder();
- }
-
- if (folder is IHasCollectionType hasCollectionType
- && string.Equals(hasCollectionType.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
- {
- request.Recursive = true;
- request.IncludeItemTypes = "Playlist";
- }
-
- bool isInEnabledFolder = user.GetPreference(PreferenceKind.EnabledFolders).Any(i => new Guid(i) == item.Id)
- // Assume all folders inside an EnabledChannel are enabled
- || user.GetPreference(PreferenceKind.EnabledChannels).Any(i => new Guid(i) == item.Id);
-
- var collectionFolders = _libraryManager.GetCollectionFolders(item);
- foreach (var collectionFolder in collectionFolders)
- {
- if (user.GetPreference(PreferenceKind.EnabledFolders).Contains(
- collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture),
- StringComparer.OrdinalIgnoreCase))
- {
- isInEnabledFolder = true;
- }
- }
-
- if (!(item is UserRootFolder)
- && !isInEnabledFolder
- && !user.HasPermission(PermissionKind.EnableAllFolders)
- && !user.HasPermission(PermissionKind.EnableAllChannels))
- {
- Logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Username, item.Name);
- return new QueryResult<BaseItem>
- {
- Items = Array.Empty<BaseItem>(),
- TotalRecordCount = 0,
- StartIndex = 0
- };
- }
-
- if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || !(item is UserRootFolder))
- {
- return folder.GetItems(GetItemsQuery(request, dtoOptions, user));
- }
-
- var itemsArray = folder.GetChildren(user, true);
- return new QueryResult<BaseItem>
- {
- Items = itemsArray,
- TotalRecordCount = itemsArray.Count,
- StartIndex = 0
- };
- }
-
- private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions, User user)
- {
- var query = new InternalItemsQuery(user)
- {
- IsPlayed = request.IsPlayed,
- MediaTypes = request.GetMediaTypes(),
- IncludeItemTypes = request.GetIncludeItemTypes(),
- ExcludeItemTypes = request.GetExcludeItemTypes(),
- Recursive = request.Recursive,
- OrderBy = request.GetOrderBy(),
-
- IsFavorite = request.IsFavorite,
- Limit = request.Limit,
- StartIndex = request.StartIndex,
- IsMissing = request.IsMissing,
- IsUnaired = request.IsUnaired,
- CollapseBoxSetItems = request.CollapseBoxSetItems,
- NameLessThan = request.NameLessThan,
- NameStartsWith = request.NameStartsWith,
- NameStartsWithOrGreater = request.NameStartsWithOrGreater,
- HasImdbId = request.HasImdbId,
- IsPlaceHolder = request.IsPlaceHolder,
- IsLocked = request.IsLocked,
- MinWidth = request.MinWidth,
- MinHeight = request.MinHeight,
- MaxWidth = request.MaxWidth,
- MaxHeight = request.MaxHeight,
- Is3D = request.Is3D,
- HasTvdbId = request.HasTvdbId,
- HasTmdbId = request.HasTmdbId,
- HasOverview = request.HasOverview,
- HasOfficialRating = request.HasOfficialRating,
- HasParentalRating = request.HasParentalRating,
- HasSpecialFeature = request.HasSpecialFeature,
- HasSubtitles = request.HasSubtitles,
- HasThemeSong = request.HasThemeSong,
- HasThemeVideo = request.HasThemeVideo,
- HasTrailer = request.HasTrailer,
- IsHD = request.IsHD,
- Is4K = request.Is4K,
- Tags = request.GetTags(),
- OfficialRatings = request.GetOfficialRatings(),
- Genres = request.GetGenres(),
- ArtistIds = GetGuids(request.ArtistIds),
- AlbumArtistIds = GetGuids(request.AlbumArtistIds),
- ContributingArtistIds = GetGuids(request.ContributingArtistIds),
- GenreIds = GetGuids(request.GenreIds),
- StudioIds = GetGuids(request.StudioIds),
- Person = request.Person,
- PersonIds = GetGuids(request.PersonIds),
- PersonTypes = request.GetPersonTypes(),
- Years = request.GetYears(),
- ImageTypes = request.GetImageTypes(),
- VideoTypes = request.GetVideoTypes(),
- AdjacentTo = request.AdjacentTo,
- ItemIds = GetGuids(request.Ids),
- MinCommunityRating = request.MinCommunityRating,
- MinCriticRating = request.MinCriticRating,
- ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId),
- ParentIndexNumber = request.ParentIndexNumber,
- EnableTotalRecordCount = request.EnableTotalRecordCount,
- ExcludeItemIds = GetGuids(request.ExcludeItemIds),
- DtoOptions = dtoOptions,
- SearchTerm = request.SearchTerm
- };
-
- if (!string.IsNullOrWhiteSpace(request.Ids) || !string.IsNullOrWhiteSpace(request.SearchTerm))
- {
- query.CollapseBoxSetItems = false;
- }
-
- foreach (var filter in request.GetFilters())
- {
- switch (filter)
- {
- case ItemFilter.Dislikes:
- query.IsLiked = false;
- break;
- case ItemFilter.IsFavorite:
- query.IsFavorite = true;
- break;
- case ItemFilter.IsFavoriteOrLikes:
- query.IsFavoriteOrLiked = true;
- break;
- case ItemFilter.IsFolder:
- query.IsFolder = true;
- break;
- case ItemFilter.IsNotFolder:
- query.IsFolder = false;
- break;
- case ItemFilter.IsPlayed:
- query.IsPlayed = true;
- break;
- case ItemFilter.IsResumable:
- query.IsResumable = true;
- break;
- case ItemFilter.IsUnplayed:
- query.IsPlayed = false;
- break;
- case ItemFilter.Likes:
- query.IsLiked = true;
- break;
- }
- }
-
- if (!string.IsNullOrEmpty(request.MinDateLastSaved))
- {
- query.MinDateLastSaved = DateTime.Parse(request.MinDateLastSaved, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MinDateLastSavedForUser))
- {
- query.MinDateLastSavedForUser = DateTime.Parse(request.MinDateLastSavedForUser, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MinPremiereDate))
- {
- query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- if (!string.IsNullOrEmpty(request.MaxPremiereDate))
- {
- query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
- }
-
- // Filter by Series Status
- if (!string.IsNullOrEmpty(request.SeriesStatus))
- {
- query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
- }
-
- // ExcludeLocationTypes
- if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
- {
- var excludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
- if (excludeLocationTypes.Contains(LocationType.Virtual))
- {
- query.IsVirtualItem = false;
- }
- }
-
- if (!string.IsNullOrEmpty(request.LocationTypes))
- {
- var requestedLocationTypes =
- request.LocationTypes.Split(',');
-
- if (requestedLocationTypes.Length > 0 && requestedLocationTypes.Length < 4)
- {
- query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual.ToString());
- }
- }
-
- // Min official rating
- if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
- {
- query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
- }
-
- // Max official rating
- if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating))
- {
- query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating);
- }
-
- // Artists
- if (!string.IsNullOrEmpty(request.Artists))
- {
- query.ArtistIds = request.Artists.Split('|').Select(i =>
- {
- try
- {
- return _libraryManager.GetArtist(i, new DtoOptions(false));
- }
- catch
- {
- return null;
- }
- }).Where(i => i != null).Select(i => i.Id).ToArray();
- }
-
- // ExcludeArtistIds
- if (!string.IsNullOrWhiteSpace(request.ExcludeArtistIds))
- {
- query.ExcludeArtistIds = GetGuids(request.ExcludeArtistIds);
- }
-
- if (!string.IsNullOrWhiteSpace(request.AlbumIds))
- {
- query.AlbumIds = GetGuids(request.AlbumIds);
- }
-
- // Albums
- if (!string.IsNullOrEmpty(request.Albums))
- {
- query.AlbumIds = request.Albums.Split('|').SelectMany(i =>
- {
- return _libraryManager.GetItemIds(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
- Name = i,
- Limit = 1
- });
- }).ToArray();
- }
-
- // Studios
- if (!string.IsNullOrEmpty(request.Studios))
- {
- query.StudioIds = request.Studios.Split('|').Select(i =>
- {
- try
- {
- return _libraryManager.GetStudio(i);
- }
- catch
- {
- return null;
- }
- }).Where(i => i != null).Select(i => i.Id).ToArray();
- }
-
- // Apply default sorting if none requested
- if (query.OrderBy.Count == 0)
- {
- // Albums by artist
- if (query.ArtistIds.Length > 0 && query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], "MusicAlbum", StringComparison.OrdinalIgnoreCase))
- {
- query.OrderBy = new[]
- {
- new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending),
- new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending)
- };
- }
- }
-
- return query;
- }
- }
-
- /// <summary>
- /// Class DateCreatedComparer.
- /// </summary>
- public class DateCreatedComparer : IComparer<BaseItem>
- {
- /// <summary>
- /// Compares the specified x.
- /// </summary>
- /// <param name="x">The x.</param>
- /// <param name="y">The y.</param>
- /// <returns>System.Int32.</returns>
- public int Compare(BaseItem x, BaseItem y)
- {
- return x.DateCreated.CompareTo(y.DateCreated);
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
deleted file mode 100644
index 7924339ed..000000000
--- 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
-{
- /// <summary>
- /// Class GetPersons.
- /// </summary>
- [Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
- public class GetPersons : GetItemsByName
- {
- }
-
- /// <summary>
- /// Class GetPerson.
- /// </summary>
- [Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")]
- public class GetPerson : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The person name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class PersonsService.
- /// </summary>
- [Authenticated]
- public class PersonsService : BaseItemsByNameService<Person>
- {
- public PersonsService(
- ILogger<PersonsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- userDataRepository,
- dtoService,
- authorizationContext)
- {
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPerson request)
- {
- var result = GetItem(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the item.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- private BaseItemDto GetItem(GetPerson request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- var item = GetPerson(request.Name, LibraryManager, dtoOptions);
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
-
- return DtoService.GetBaseItemDto(item, dtoOptions, user);
- }
-
- return DtoService.GetBaseItemDto(item, dtoOptions);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetPersons request)
- {
- return GetResultSlim(request);
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
- protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
- {
- throw new NotImplementedException();
- }
-
- protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- var items = LibraryManager.GetPeopleItems(new InternalPeopleQuery
- {
- PersonTypes = query.PersonTypes,
- NameContains = query.NameContains ?? query.SearchTerm
- });
-
- if ((query.IsFavorite ?? false) && query.User != null)
- {
- items = items.Where(i => UserDataRepository.GetUserData(query.User, i).IsFavorite).ToList();
- }
-
- return new QueryResult<(BaseItem, ItemCounts)>
- {
- TotalRecordCount = items.Count,
- Items = items.Take(query.Limit ?? int.MaxValue).Select(i => (i as BaseItem, new ItemCounts())).ToArray()
- };
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
deleted file mode 100644
index d809cc2e7..000000000
--- 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
-{
- /// <summary>
- /// Class MarkPlayedItem.
- /// </summary>
- [Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")]
- public class MarkPlayedItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
-
- [ApiMember(Name = "DatePlayed", Description = "The date the item was played (if any). Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string DatePlayed { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class MarkUnplayedItem.
- /// </summary>
- [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")]
- public class MarkUnplayedItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/Playing", "POST", Summary = "Reports playback has started within a session")]
- public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
- {
- }
-
- [Route("/Sessions/Playing/Progress", "POST", Summary = "Reports playback progress within a session")]
- public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
- {
- }
-
- [Route("/Sessions/Playing/Ping", "POST", Summary = "Pings a playback session")]
- public class PingPlaybackSession : IReturnVoid
- {
- [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlaySessionId { get; set; }
- }
-
- [Route("/Sessions/Playing/Stopped", "POST", Summary = "Reports playback has stopped within a session")]
- public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
- {
- }
-
- /// <summary>
- /// Class OnPlaybackStart.
- /// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")]
- public class OnPlaybackStart : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaSourceId { get; set; }
-
- [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool CanSeek { get; set; }
-
- [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? AudioStreamIndex { get; set; }
-
- [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? SubtitleStreamIndex { get; set; }
-
- [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public PlayMethod PlayMethod { get; set; }
-
- [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string LiveStreamId { get; set; }
-
- [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlaySessionId { get; set; }
- }
-
- /// <summary>
- /// Class OnPlaybackProgress.
- /// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")]
- public class OnPlaybackProgress : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets the position ticks.
- /// </summary>
- /// <value>The position ticks.</value>
- [ApiMember(Name = "PositionTicks", Description = "Optional. The current position, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public long? PositionTicks { get; set; }
-
- [ApiMember(Name = "IsPaused", Description = "Indicates if the player is paused.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool IsPaused { get; set; }
-
- [ApiMember(Name = "IsMuted", Description = "Indicates if the player is muted.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool IsMuted { get; set; }
-
- [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? AudioStreamIndex { get; set; }
-
- [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? SubtitleStreamIndex { get; set; }
-
- [ApiMember(Name = "VolumeLevel", Description = "Scale of 0-100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? VolumeLevel { get; set; }
-
- [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public PlayMethod PlayMethod { get; set; }
-
- [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string LiveStreamId { get; set; }
-
- [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlaySessionId { get; set; }
-
- [ApiMember(Name = "RepeatMode", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public RepeatMode RepeatMode { get; set; }
- }
-
- /// <summary>
- /// Class OnPlaybackStopped.
- /// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")]
- public class OnPlaybackStopped : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string MediaSourceId { get; set; }
-
- [ApiMember(Name = "NextMediaType", Description = "The next media type that will play", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string NextMediaType { get; set; }
-
- /// <summary>
- /// Gets or sets the position ticks.
- /// </summary>
- /// <value>The position ticks.</value>
- [ApiMember(Name = "PositionTicks", Description = "Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "DELETE")]
- public long? PositionTicks { get; set; }
-
- [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string LiveStreamId { get; set; }
-
- [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlaySessionId { get; set; }
- }
-
- [Authenticated]
- public class PlaystateService : BaseApiService
- {
- private readonly IUserManager _userManager;
- private readonly IUserDataManager _userDataRepository;
- private readonly ILibraryManager _libraryManager;
- private readonly ISessionManager _sessionManager;
- private readonly ISessionContext _sessionContext;
- private readonly IAuthorizationContext _authContext;
-
- public PlaystateService(
- ILogger<PlaystateService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- IUserDataManager userDataRepository,
- ILibraryManager libraryManager,
- ISessionManager sessionManager,
- ISessionContext sessionContext,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _userDataRepository = userDataRepository;
- _libraryManager = libraryManager;
- _sessionManager = sessionManager;
- _sessionContext = sessionContext;
- _authContext = authContext;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(MarkPlayedItem request)
- {
- var result = MarkPlayed(request);
-
- return ToOptimizedResult(result);
- }
-
- private UserItemDataDto MarkPlayed(MarkPlayedItem request)
- {
- var user = _userManager.GetUserById(Guid.Parse(request.UserId));
-
- DateTime? datePlayed = null;
-
- if (!string.IsNullOrEmpty(request.DatePlayed))
- {
- datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
- }
-
- var session = GetSession(_sessionContext);
-
- var dto = UpdatePlayedStatus(user, request.Id, true, datePlayed);
-
- foreach (var additionalUserInfo in session.AdditionalUsers)
- {
- var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
-
- UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed);
- }
-
- return dto;
- }
-
- private PlayMethod ValidatePlayMethod(PlayMethod method, string playSessionId)
- {
- if (method == PlayMethod.Transcode)
- {
- var job = string.IsNullOrWhiteSpace(playSessionId) ? null : ApiEntryPoint.Instance.GetTranscodingJob(playSessionId);
- if (job == null)
- {
- return PlayMethod.DirectPlay;
- }
- }
-
- return method;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(OnPlaybackStart request)
- {
- Post(new ReportPlaybackStart
- {
- CanSeek = request.CanSeek,
- ItemId = new Guid(request.Id),
- MediaSourceId = request.MediaSourceId,
- AudioStreamIndex = request.AudioStreamIndex,
- SubtitleStreamIndex = request.SubtitleStreamIndex,
- PlayMethod = request.PlayMethod,
- PlaySessionId = request.PlaySessionId,
- LiveStreamId = request.LiveStreamId
- });
- }
-
- public void Post(ReportPlaybackStart request)
- {
- request.PlayMethod = ValidatePlayMethod(request.PlayMethod, request.PlaySessionId);
-
- request.SessionId = GetSession(_sessionContext).Id;
-
- var task = _sessionManager.OnPlaybackStart(request);
-
- Task.WaitAll(task);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(OnPlaybackProgress request)
- {
- Post(new ReportPlaybackProgress
- {
- ItemId = new Guid(request.Id),
- PositionTicks = request.PositionTicks,
- IsMuted = request.IsMuted,
- IsPaused = request.IsPaused,
- MediaSourceId = request.MediaSourceId,
- AudioStreamIndex = request.AudioStreamIndex,
- SubtitleStreamIndex = request.SubtitleStreamIndex,
- VolumeLevel = request.VolumeLevel,
- PlayMethod = request.PlayMethod,
- PlaySessionId = request.PlaySessionId,
- LiveStreamId = request.LiveStreamId,
- RepeatMode = request.RepeatMode
- });
- }
-
- public void Post(ReportPlaybackProgress request)
- {
- request.PlayMethod = ValidatePlayMethod(request.PlayMethod, request.PlaySessionId);
-
- request.SessionId = GetSession(_sessionContext).Id;
-
- var task = _sessionManager.OnPlaybackProgress(request);
-
- Task.WaitAll(task);
- }
-
- public void Post(PingPlaybackSession request)
- {
- ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId, null);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Delete(OnPlaybackStopped request)
- {
- return Post(new ReportPlaybackStopped
- {
- ItemId = new Guid(request.Id),
- PositionTicks = request.PositionTicks,
- MediaSourceId = request.MediaSourceId,
- PlaySessionId = request.PlaySessionId,
- LiveStreamId = request.LiveStreamId,
- NextMediaType = request.NextMediaType
- });
- }
-
- public async Task Post(ReportPlaybackStopped request)
- {
- Logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", request.PlaySessionId ?? string.Empty);
-
- if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
- {
- await ApiEntryPoint.Instance.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true);
- }
-
- request.SessionId = GetSession(_sessionContext).Id;
-
- await _sessionManager.OnPlaybackStopped(request);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Delete(MarkUnplayedItem request)
- {
- var task = MarkUnplayed(request);
-
- return ToOptimizedResult(task);
- }
-
- private UserItemDataDto MarkUnplayed(MarkUnplayedItem request)
- {
- var user = _userManager.GetUserById(Guid.Parse(request.UserId));
-
- var session = GetSession(_sessionContext);
-
- var dto = UpdatePlayedStatus(user, request.Id, false, null);
-
- foreach (var additionalUserInfo in session.AdditionalUsers)
- {
- var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
-
- UpdatePlayedStatus(additionalUser, request.Id, false, null);
- }
-
- return dto;
- }
-
- /// <summary>
- /// Updates the played status.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="itemId">The item id.</param>
- /// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
- /// <param name="datePlayed">The date played.</param>
- /// <returns>Task.</returns>
- private UserItemDataDto UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed)
- {
- var item = _libraryManager.GetItemById(itemId);
-
- if (wasPlayed)
- {
- item.MarkPlayed(user, datePlayed, true);
- }
- else
- {
- item.MarkUnplayed(user);
- }
-
- return _userDataRepository.GetUserDataDto(item, user);
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs
deleted file mode 100644
index 66350955f..000000000
--- 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
-{
- /// <summary>
- /// Class GetStudios.
- /// </summary>
- [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
- public class GetStudios : GetItemsByName
- {
- }
-
- /// <summary>
- /// Class GetStudio.
- /// </summary>
- [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
- public class GetStudio : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- [ApiMember(Name = "Name", Description = "The studio name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class StudiosService.
- /// </summary>
- [Authenticated]
- public class StudiosService : BaseItemsByNameService<Studio>
- {
- public StudiosService(
- ILogger<StudiosService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- userDataRepository,
- dtoService,
- authorizationContext)
- {
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetStudio request)
- {
- var result = GetItem(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the item.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- private BaseItemDto GetItem(GetStudio request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- var item = GetStudio(request.Name, LibraryManager, dtoOptions);
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
-
- return DtoService.GetBaseItemDto(item, dtoOptions, user);
- }
-
- return DtoService.GetBaseItemDto(item, dtoOptions);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetStudios request)
- {
- var result = GetResultSlim(request);
-
- return ToOptimizedResult(result);
- }
-
- protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- return LibraryManager.GetStudios(query);
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
- protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
deleted file mode 100644
index f9cbba410..000000000
--- 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
-{
- /// <summary>
- /// Class GetItem.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")]
- public class GetItem : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetItem.
- /// </summary>
- [Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")]
- public class GetRootFolder : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class GetIntros.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")]
- public class GetIntros : IReturn<QueryResult<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the item id.
- /// </summary>
- /// <value>The item id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class MarkFavoriteItem.
- /// </summary>
- [Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")]
- public class MarkFavoriteItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class UnmarkFavoriteItem.
- /// </summary>
- [Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")]
- public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class ClearUserItemRating.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")]
- public class DeleteUserItemRating : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUserItemRating.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")]
- public class UpdateUserItemRating : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this <see cref="UpdateUserItemRating" /> is likes.
- /// </summary>
- /// <value><c>true</c> if likes; otherwise, <c>false</c>.</value>
- [ApiMember(Name = "Likes", Description = "Whether the user likes the item or not. true/false", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool Likes { get; set; }
- }
-
- /// <summary>
- /// Class GetLocalTrailers.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")]
- public class GetLocalTrailers : IReturn<BaseItemDto[]>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class GetSpecialFeatures.
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")]
- public class GetSpecialFeatures : IReturn<BaseItemDto[]>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Movie Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [Route("/Users/{UserId}/Items/Latest", "GET", Summary = "Gets latest media")]
- public class GetLatestMedia : IReturn<BaseItemDto[]>, IHasDtoOptions
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "Limit", Description = "Limit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int Limit { get; set; }
-
- [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid ParentId { get; set; }
-
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string IncludeItemTypes { get; set; }
-
- [ApiMember(Name = "IsFolder", Description = "Filter by items that are folders, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsFolder { get; set; }
-
- [ApiMember(Name = "IsPlayed", Description = "Filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsPlayed { get; set; }
-
- [ApiMember(Name = "GroupItems", Description = "Whether or not to group items into a parent container.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool GroupItems { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- public GetLatestMedia()
- {
- Limit = 20;
- GroupItems = true;
- }
- }
-
- /// <summary>
- /// Class UserLibraryService.
- /// </summary>
- [Authenticated]
- public class UserLibraryService : BaseApiService
- {
- private readonly IUserManager _userManager;
- private readonly IUserDataManager _userDataRepository;
- private readonly ILibraryManager _libraryManager;
- private readonly IDtoService _dtoService;
- private readonly IUserViewManager _userViewManager;
- private readonly IFileSystem _fileSystem;
- private readonly IAuthorizationContext _authContext;
-
- public UserLibraryService(
- ILogger<UserLibraryService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IUserViewManager userViewManager,
- IFileSystem fileSystem,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _userDataRepository = userDataRepository;
- _dtoService = dtoService;
- _userViewManager = userViewManager;
- _fileSystem = fileSystem;
- _authContext = authContext;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSpecialFeatures request)
- {
- var result = GetAsync(request);
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetLatestMedia request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- if (!request.IsPlayed.HasValue)
- {
- if (user.HidePlayedInLatest)
- {
- request.IsPlayed = false;
- }
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var list = _userViewManager.GetLatestItems(new LatestItemsQuery
- {
- GroupItems = request.GroupItems,
- IncludeItemTypes = ApiEntryPoint.Split(request.IncludeItemTypes, ',', true),
- IsPlayed = request.IsPlayed,
- Limit = request.Limit,
- ParentId = request.ParentId,
- UserId = request.UserId,
- }, dtoOptions);
-
- var dtos = list.Select(i =>
- {
- var item = i.Item2[0];
- var childCount = 0;
-
- if (i.Item1 != null && (i.Item2.Count > 1 || i.Item1 is MusicAlbum))
- {
- item = i.Item1;
- childCount = i.Item2.Count;
- }
-
- var dto = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
- dto.ChildCount = childCount;
-
- return dto;
- });
-
- return ToOptimizedResult(dtos.ToArray());
- }
-
- private BaseItemDto[] GetAsync(GetSpecialFeatures request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ?
- _libraryManager.GetUserRootFolder() :
- _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtos = item
- .GetExtras(BaseItem.DisplayExtraTypes)
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
-
- return dtos.ToArray();
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetLocalTrailers request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer })
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
- .ToArray();
-
- if (item is IHasTrailers hasTrailers)
- {
- var trailers = hasTrailers.GetTrailers();
- var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item);
- var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count];
- dtosExtras.CopyTo(allTrailers, 0);
- dtosTrailers.CopyTo(allTrailers, dtosExtras.Length);
- return ToOptimizedResult(allTrailers);
- }
-
- return ToOptimizedResult(dtosExtras);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Get(GetItem request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
- await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
- return ToOptimizedResult(result);
- }
-
- private async Task RefreshItemOnDemandIfNeeded(BaseItem item)
- {
- if (item is Person)
- {
- var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary);
- var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 3;
-
- if (!hasMetdata)
- {
- var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem))
- {
- MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
- ImageRefreshMode = MetadataRefreshMode.FullRefresh,
- ForceSave = performFullRefresh
- };
-
- await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false);
- }
- }
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetRootFolder request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = _libraryManager.GetUserRootFolder();
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Get(GetIntros request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(request.Id);
-
- var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = dtos.Length
- };
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(MarkFavoriteItem request)
- {
- var dto = MarkFavorite(request.UserId, request.Id, true);
-
- return ToOptimizedResult(dto);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Delete(UnmarkFavoriteItem request)
- {
- var dto = MarkFavorite(request.UserId, request.Id, false);
-
- return ToOptimizedResult(dto);
- }
-
- /// <summary>
- /// Marks the favorite.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="itemId">The item id.</param>
- /// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
- private UserItemDataDto MarkFavorite(Guid userId, Guid itemId, bool isFavorite)
- {
- var user = _userManager.GetUserById(userId);
-
- var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
- // Get the user data for this item
- var data = _userDataRepository.GetUserData(user, item);
-
- // Set favorite status
- data.IsFavorite = isFavorite;
-
- _userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
-
- return _userDataRepository.GetUserDataDto(item, user);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Delete(DeleteUserItemRating request)
- {
- var dto = UpdateUserItemRating(request.UserId, request.Id, null);
-
- return ToOptimizedResult(dto);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(UpdateUserItemRating request)
- {
- var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes);
-
- return ToOptimizedResult(dto);
- }
-
- /// <summary>
- /// Updates the user item rating.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="itemId">The item id.</param>
- /// <param name="likes">if set to <c>true</c> [likes].</param>
- private UserItemDataDto UpdateUserItemRating(Guid userId, Guid itemId, bool? likes)
- {
- var user = _userManager.GetUserById(userId);
-
- var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
- // Get the user data for this item
- var data = _userDataRepository.GetUserData(user, item);
-
- data.Likes = likes;
-
- _userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
-
- return _userDataRepository.GetUserDataDto(item, user);
- }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
deleted file mode 100644
index 6f1620ddd..000000000
--- 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<QueryResult<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? IncludeExternalContent { get; set; }
-
- public bool IncludeHidden { get; set; }
-
- public string PresetViews { get; set; }
- }
-
- [Route("/Users/{UserId}/GroupingOptions", "GET")]
- public class GetGroupingOptions : IReturn<SpecialViewOption[]>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- public class UserViewsService : BaseApiService
- {
- private readonly IUserManager _userManager;
- private readonly IUserViewManager _userViewManager;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
- private readonly ILibraryManager _libraryManager;
-
- public UserViewsService(
- ILogger<UserViewsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- IUserViewManager userViewManager,
- IDtoService dtoService,
- IAuthorizationContext authContext,
- ILibraryManager libraryManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _userViewManager = userViewManager;
- _dtoService = dtoService;
- _authContext = authContext;
- _libraryManager = libraryManager;
- }
-
- public object Get(GetUserViews request)
- {
- var query = new UserViewQuery
- {
- UserId = request.UserId
- };
-
- if (request.IncludeExternalContent.HasValue)
- {
- query.IncludeExternalContent = request.IncludeExternalContent.Value;
- }
-
- query.IncludeHidden = request.IncludeHidden;
-
- if (!string.IsNullOrWhiteSpace(request.PresetViews))
- {
- query.PresetViews = request.PresetViews.Split(',');
- }
-
- var app = _authContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
- if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
- {
- query.PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows };
- }
-
- var folders = _userViewManager.GetUserViews(query);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
- var fields = dtoOptions.Fields.ToList();
-
- fields.Add(ItemFields.PrimaryImageAspectRatio);
- fields.Add(ItemFields.DisplayPreferencesId);
- fields.Remove(ItemFields.BasicSyncInfo);
- dtoOptions.Fields = fields.ToArray();
-
- var user = _userManager.GetUserById(request.UserId);
-
- var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
- .ToArray();
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = dtos.Length
- };
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetGroupingOptions request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var list = _libraryManager.GetUserRootFolder()
- .GetChildren(user, true)
- .OfType<Folder>()
- .Where(UserView.IsEligibleForGrouping)
- .Select(i => new SpecialViewOption
- {
- Name = i.Name,
- Id = i.Id.ToString("N", CultureInfo.InvariantCulture)
- })
- .OrderBy(i => i.Name)
- .ToArray();
-
- return ToOptimizedResult(list);
- }
- }
-
- class SpecialViewOption
- {
- public string Name { get; set; }
-
- public string Id { get; set; }
- }
-}
diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs
deleted file mode 100644
index 0523f89fa..000000000
--- 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
-{
- /// <summary>
- /// Class GetYears.
- /// </summary>
- [Route("/Years", "GET", Summary = "Gets all years from a given item, folder, or the entire library")]
- public class GetYears : GetItemsByName
- {
- }
-
- /// <summary>
- /// Class GetYear.
- /// </summary>
- [Route("/Years/{Year}", "GET", Summary = "Gets a year")]
- public class GetYear : IReturn<BaseItemDto>
- {
- /// <summary>
- /// Gets or sets the year.
- /// </summary>
- /// <value>The year.</value>
- [ApiMember(Name = "Year", Description = "The year", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
- public int Year { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- /// <summary>
- /// Class YearsService.
- /// </summary>
- [Authenticated]
- public class YearsService : BaseItemsByNameService<Year>
- {
- public YearsService(
- ILogger<YearsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IUserDataManager userDataRepository,
- IDtoService dtoService,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- userDataRepository,
- dtoService,
- authorizationContext)
- {
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetYear request)
- {
- var result = GetItem(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the item.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- private BaseItemDto GetItem(GetYear request)
- {
- var item = LibraryManager.GetYear(request.Year);
-
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- if (!request.UserId.Equals(Guid.Empty))
- {
- var user = UserManager.GetUserById(request.UserId);
-
- return DtoService.GetBaseItemDto(item, dtoOptions, user);
- }
-
- return DtoService.GetBaseItemDto(item, dtoOptions);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetYears request)
- {
- var result = GetResult(request);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets all items.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
- protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IList<BaseItem> items)
- {
- return items
- .Select(i => i.ProductionYear ?? 0)
- .Where(i => i > 0)
- .Distinct()
- .Select(year => LibraryManager.GetYear(year));
- }
- }
-}
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
deleted file mode 100644
index 6e9d788dc..000000000
--- 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
-{
- /// <summary>
- /// Class GetUsers.
- /// </summary>
- [Route("/Users", "GET", Summary = "Gets a list of users")]
- [Authenticated]
- public class GetUsers : IReturn<UserDto[]>
- {
- [ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsHidden { get; set; }
-
- [ApiMember(Name = "IsDisabled", Description = "Optional filter by IsDisabled=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsDisabled { get; set; }
-
- [ApiMember(Name = "IsGuest", Description = "Optional filter by IsGuest=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsGuest { get; set; }
- }
-
- [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
- public class GetPublicUsers : IReturn<UserDto[]>
- {
- }
-
- /// <summary>
- /// Class GetUser.
- /// </summary>
- [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
- [Authenticated(EscapeParentalControl = true)]
- public class GetUser : IReturn<UserDto>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class DeleteUser.
- /// </summary>
- [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
- [Authenticated(Roles = "Admin")]
- public class DeleteUser : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class AuthenticateUser.
- /// </summary>
- [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")]
- public class AuthenticateUser : IReturn<AuthenticationResult>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pw { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
- }
-
- /// <summary>
- /// Class AuthenticateUser.
- /// </summary>
- [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")]
- public class AuthenticateUserByName : IReturn<AuthenticationResult>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Username", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Username { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
-
- [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pw { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUserPassword.
- /// </summary>
- [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")]
- [Authenticated]
- public class UpdateUserPassword : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- public string CurrentPassword { get; set; }
-
- public string CurrentPw { get; set; }
-
- public string NewPw { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [reset password].
- /// </summary>
- /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
- public bool ResetPassword { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUserEasyPassword.
- /// </summary>
- [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")]
- [Authenticated]
- public class UpdateUserEasyPassword : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the new password.
- /// </summary>
- /// <value>The new password.</value>
- public string NewPassword { get; set; }
-
- public string NewPw { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [reset password].
- /// </summary>
- /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
- public bool ResetPassword { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUser.
- /// </summary>
- [Route("/Users/{Id}", "POST", Summary = "Updates a user")]
- [Authenticated]
- public class UpdateUser : UserDto, IReturnVoid
- {
- }
-
- /// <summary>
- /// Class UpdateUser.
- /// </summary>
- [Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")]
- [Authenticated(Roles = "admin")]
- public class UpdateUserPolicy : UserPolicy, IReturnVoid
- {
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUser.
- /// </summary>
- [Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")]
- [Authenticated]
- public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
- {
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class CreateUser.
- /// </summary>
- [Route("/Users/New", "POST", Summary = "Creates a user")]
- [Authenticated(Roles = "Admin")]
- public class CreateUserByName : IReturn<UserDto>
- {
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Password", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
- }
-
- [Route("/Users/ForgotPassword", "POST", Summary = "Initiates the forgot password process for a local user")]
- public class ForgotPassword : IReturn<ForgotPasswordResult>
- {
- [ApiMember(Name = "EnteredUsername", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string EnteredUsername { get; set; }
- }
-
- [Route("/Users/ForgotPassword/Pin", "POST", Summary = "Redeems a forgot password pin")]
- public class ForgotPasswordPin : IReturn<PinRedeemResult>
- {
- [ApiMember(Name = "Pin", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pin { get; set; }
- }
-
- /// <summary>
- /// Class UsersService.
- /// </summary>
- public class UserService : BaseApiService
- {
- /// <summary>
- /// The user manager.
- /// </summary>
- private readonly IUserManager _userManager;
- private readonly ISessionManager _sessionMananger;
- private readonly INetworkManager _networkManager;
- private readonly IDeviceManager _deviceManager;
- private readonly IAuthorizationContext _authContext;
-
- public UserService(
- ILogger<UserService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ISessionManager sessionMananger,
- INetworkManager networkManager,
- IDeviceManager deviceManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _sessionMananger = sessionMananger;
- _networkManager = networkManager;
- _deviceManager = deviceManager;
- _authContext = authContext;
- }
-
- public object Get(GetPublicUsers request)
- {
- // If the startup wizard hasn't been completed then just return all users
- if (!ServerConfigurationManager.Configuration.IsStartupWizardCompleted)
- {
- return Get(new GetUsers
- {
- IsDisabled = false
- });
- }
-
- return Get(new GetUsers
- {
- IsHidden = false,
- IsDisabled = false
- }, true, true);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetUsers request)
- {
- return Get(request, false, false);
- }
-
- private object Get(GetUsers request, bool filterByDevice, bool filterByNetwork)
- {
- var users = _userManager.Users;
-
- if (request.IsDisabled.HasValue)
- {
- users = users.Where(i => i.HasPermission(PermissionKind.IsDisabled) == request.IsDisabled.Value);
- }
-
- if (request.IsHidden.HasValue)
- {
- users = users.Where(i => i.HasPermission(PermissionKind.IsHidden) == request.IsHidden.Value);
- }
-
- if (filterByDevice)
- {
- var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
-
- if (!string.IsNullOrWhiteSpace(deviceId))
- {
- users = users.Where(i => _deviceManager.CanAccessDevice(i, deviceId));
- }
- }
-
- if (filterByNetwork)
- {
- if (!_networkManager.IsInLocalNetwork(Request.RemoteIp))
- {
- users = users.Where(i => i.HasPermission(PermissionKind.EnableRemoteAccess));
- }
- }
-
- var result = users
- .OrderBy(u => u.Username)
- .Select(i => _userManager.GetUserDto(i, Request.RemoteIp))
- .ToArray();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetUser request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- var result = _userManager.GetUserDto(user, Request.RemoteIp);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Delete(DeleteUser request)
- {
- return DeleteAsync(request);
- }
-
- public Task DeleteAsync(DeleteUser request)
- {
- _userManager.DeleteUser(request.Id);
- _sessionMananger.RevokeUserTokens(request.Id, null);
- return Task.CompletedTask;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(AuthenticateUser request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (!string.IsNullOrEmpty(request.Password) && string.IsNullOrEmpty(request.Pw))
- {
- throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API.");
- }
-
- // Password should always be null
- return Post(new AuthenticateUserByName
- {
- Username = user.Username,
- Password = null,
- Pw = request.Pw
- });
- }
-
- public async Task<object> Post(AuthenticateUserByName request)
- {
- var auth = _authContext.GetAuthorizationInfo(Request);
-
- try
- {
- var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest
- {
- App = auth.Client,
- AppVersion = auth.Version,
- DeviceId = auth.DeviceId,
- DeviceName = auth.Device,
- Password = request.Pw,
- PasswordSha1 = request.Password,
- RemoteEndPoint = Request.RemoteIp,
- Username = request.Username
- }).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
- catch (SecurityException e)
- {
- // rethrow adding IP address to message
- throw new SecurityException($"[{Request.RemoteIp}] {e.Message}", e);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(UpdateUserPassword request)
- {
- return PostAsync(request);
- }
-
- public async Task PostAsync(UpdateUserPassword request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (request.ResetPassword)
- {
- await _userManager.ResetPassword(user).ConfigureAwait(false);
- }
- else
- {
- var success = await _userManager.AuthenticateUser(
- user.Username,
- request.CurrentPw,
- request.CurrentPassword,
- Request.RemoteIp,
- false).ConfigureAwait(false);
-
- if (success == null)
- {
- throw new ArgumentException("Invalid user or password entered.");
- }
-
- await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false);
-
- var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
-
- _sessionMananger.RevokeUserTokens(user.Id, currentToken);
- }
- }
-
- public void Post(UpdateUserEasyPassword request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (request.ResetPassword)
- {
- _userManager.ResetEasyPassword(user);
- }
- else
- {
- _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public async Task Post(UpdateUser request)
- {
- var id = Guid.Parse(GetPathValue(1));
-
- AssertCanUpdateUser(_authContext, _userManager, id, false);
-
- var dtoUser = request;
-
- var user = _userManager.GetUserById(id);
-
- if (string.Equals(user.Username, dtoUser.Name, StringComparison.Ordinal))
- {
- await _userManager.UpdateUserAsync(user);
- _userManager.UpdateConfiguration(user.Id, dtoUser.Configuration);
- }
- else
- {
- await _userManager.RenameUser(user, dtoUser.Name).ConfigureAwait(false);
-
- _userManager.UpdateConfiguration(dtoUser.Id, dtoUser.Configuration);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Post(CreateUserByName request)
- {
- var newUser = _userManager.CreateUser(request.Name);
-
- // no need to authenticate password for new user
- if (request.Password != null)
- {
- await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
- }
-
- var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(ForgotPassword request)
- {
- var isLocal = Request.IsLocal || _networkManager.IsInLocalNetwork(Request.RemoteIp);
-
- var result = await _userManager.StartForgotPasswordProcess(request.EnteredUsername, isLocal).ConfigureAwait(false);
-
- return result;
- }
-
- public async Task<object> Post(ForgotPasswordPin request)
- {
- var result = await _userManager.RedeemPasswordResetPin(request.Pin).ConfigureAwait(false);
-
- return result;
- }
-
- public void Post(UpdateUserConfiguration request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
-
- _userManager.UpdateConfiguration(request.Id, request);
- }
-
- public void Post(UpdateUserPolicy request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- // If removing admin access
- if (!request.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))
- {
- if (_userManager.Users.Count(i => i.HasPermission(PermissionKind.IsAdministrator)) == 1)
- {
- throw new ArgumentException("There must be at least one user in the system with administrative access.");
- }
- }
-
- // If disabling
- if (request.IsDisabled && user.HasPermission(PermissionKind.IsAdministrator))
- {
- throw new ArgumentException("Administrators cannot be disabled.");
- }
-
- // If disabling
- if (request.IsDisabled && !user.HasPermission(PermissionKind.IsDisabled))
- {
- if (_userManager.Users.Count(i => !i.HasPermission(PermissionKind.IsDisabled)) == 1)
- {
- throw new ArgumentException("There must be at least one enabled user in the system.");
- }
-
- var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
- _sessionMananger.RevokeUserTokens(user.Id, currentToken);
- }
-
- _userManager.UpdatePolicy(request.Id, request);
- }
- }
-}