aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs4
-rw-r--r--MediaBrowser.Api/BaseApiService.cs5
-rw-r--r--MediaBrowser.Api/ChannelService.cs341
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs104
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs285
-rw-r--r--MediaBrowser.Api/IHasDtoOptions.cs1
-rw-r--r--MediaBrowser.Api/IHasItemFields.cs3
-rw-r--r--MediaBrowser.Api/Images/ImageRequest.cs12
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs12
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs1279
-rw-r--r--MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs80
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj4
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs418
-rw-r--r--MediaBrowser.Api/Movies/TrailersService.cs89
-rw-r--r--MediaBrowser.Api/Music/InstantMixService.cs197
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs16
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs5
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs18
-rw-r--r--MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs6
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs10
-rw-r--r--MediaBrowser.Api/Playback/Progressive/AudioService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs10
-rw-r--r--MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs6
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs5
-rw-r--r--MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs6
-rw-r--r--MediaBrowser.Api/Playback/StreamRequest.cs6
-rw-r--r--MediaBrowser.Api/Playback/UniversalAudioService.cs21
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs234
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs2
-rw-r--r--MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs4
-rw-r--r--MediaBrowser.Api/SimilarItemsHelper.cs223
-rw-r--r--MediaBrowser.Api/SyncPlay/SyncPlayService.cs104
-rw-r--r--MediaBrowser.Api/System/ActivityLogWebSocketListener.cs4
-rw-r--r--MediaBrowser.Api/TranscodingJob.cs8
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs143
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs388
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs475
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs140
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs514
-rw-r--r--MediaBrowser.Api/UserLibrary/MusicGenresService.cs124
-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.cs146
-rw-r--r--MediaBrowser.Api/UserLibrary/YearsService.cs131
47 files changed, 137 insertions, 6761 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 9e651fb197..b041effb2e 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api
private readonly IMediaSourceManager _mediaSourceManager;
/// <summary>
- /// The active transcoding jobs
+ /// The active transcoding jobs.
/// </summary>
private readonly List<TranscodingJob> _activeTranscodingJobs = new List<TranscodingJob>();
@@ -293,7 +293,7 @@ namespace MediaBrowser.Api
/// <summary>
/// <summary>
- /// The progressive
+ /// The progressive.
/// </summary>
/// Called when [transcode failed to start].
/// </summary>
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 2ece16ee15..63a31a7452 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -17,7 +17,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api
{
/// <summary>
- /// Class BaseApiService
+ /// Class BaseApiService.
/// </summary>
public abstract class BaseApiService : IService, IRequiresRequest
{
@@ -268,7 +268,6 @@ namespace MediaBrowser.Api
Name = name.Replace(BaseItem.SlugChar, '&'),
IncludeItemTypes = new[] { typeof(T).Name },
DtoOptions = dtoOptions
-
}).OfType<T>().FirstOrDefault();
result ??= libraryManager.GetItemList(new InternalItemsQuery
@@ -276,7 +275,6 @@ namespace MediaBrowser.Api
Name = name.Replace(BaseItem.SlugChar, '/'),
IncludeItemTypes = new[] { typeof(T).Name },
DtoOptions = dtoOptions
-
}).OfType<T>().FirstOrDefault();
result ??= libraryManager.GetItemList(new InternalItemsQuery
@@ -284,7 +282,6 @@ namespace MediaBrowser.Api
Name = name.Replace(BaseItem.SlugChar, '?'),
IncludeItemTypes = new[] { typeof(T).Name },
DtoOptions = dtoOptions
-
}).OfType<T>().FirstOrDefault();
return result;
diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs
deleted file mode 100644
index fd9b8c3968..0000000000
--- a/MediaBrowser.Api/ChannelService.cs
+++ /dev/null
@@ -1,341 +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/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
deleted file mode 100644
index dd3f3e738a..0000000000
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ /dev/null
@@ -1,104 +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/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
deleted file mode 100644
index 82d471412d..0000000000
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- /// <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/IHasDtoOptions.cs b/MediaBrowser.Api/IHasDtoOptions.cs
index 03d3b3692f..33d498e8bd 100644
--- a/MediaBrowser.Api/IHasDtoOptions.cs
+++ b/MediaBrowser.Api/IHasDtoOptions.cs
@@ -3,6 +3,7 @@ namespace MediaBrowser.Api
public interface IHasDtoOptions : IHasItemFields
{
bool? EnableImages { get; set; }
+
bool? EnableUserData { get; set; }
int? ImageTypeLimit { get; set; }
diff --git a/MediaBrowser.Api/IHasItemFields.cs b/MediaBrowser.Api/IHasItemFields.cs
index 85b4a7e2d2..ad4f1b4891 100644
--- a/MediaBrowser.Api/IHasItemFields.cs
+++ b/MediaBrowser.Api/IHasItemFields.cs
@@ -5,7 +5,7 @@ using MediaBrowser.Model.Querying;
namespace MediaBrowser.Api
{
/// <summary>
- /// Interface IHasItemFields
+ /// Interface IHasItemFields.
/// </summary>
public interface IHasItemFields
{
@@ -43,7 +43,6 @@ namespace MediaBrowser.Api
}
return null;
-
}).Where(i => i.HasValue).Select(i => i.Value).ToArray();
}
}
diff --git a/MediaBrowser.Api/Images/ImageRequest.cs b/MediaBrowser.Api/Images/ImageRequest.cs
index 71ff09b63f..0f3455548d 100644
--- a/MediaBrowser.Api/Images/ImageRequest.cs
+++ b/MediaBrowser.Api/Images/ImageRequest.cs
@@ -4,30 +4,30 @@ using MediaBrowser.Model.Services;
namespace MediaBrowser.Api.Images
{
/// <summary>
- /// Class ImageRequest
+ /// Class ImageRequest.
/// </summary>
public class ImageRequest : DeleteImageRequest
{
/// <summary>
- /// The max width
+ /// The max width.
/// </summary>
[ApiMember(Name = "MaxWidth", Description = "The maximum image width to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? MaxWidth { get; set; }
/// <summary>
- /// The max height
+ /// The max height.
/// </summary>
[ApiMember(Name = "MaxHeight", Description = "The maximum image height to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? MaxHeight { get; set; }
/// <summary>
- /// The width
+ /// The width.
/// </summary>
[ApiMember(Name = "Width", Description = "The fixed image width to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Width { get; set; }
/// <summary>
- /// The height
+ /// The height.
/// </summary>
[ApiMember(Name = "Height", Description = "The fixed image height to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Height { get; set; }
@@ -79,7 +79,7 @@ namespace MediaBrowser.Api.Images
}
/// <summary>
- /// Class DeleteImageRequest
+ /// Class DeleteImageRequest.
/// </summary>
public class DeleteImageRequest
{
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index a98266e0d2..55859d9f17 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Api.Images
}
/// <summary>
- /// Class GetPersonImage
+ /// Class GetPersonImage.
/// </summary>
[Route("/Artists/{Name}/Images/{Type}", "GET")]
[Route("/Artists/{Name}/Images/{Type}/{Index}", "GET")]
@@ -78,7 +78,7 @@ namespace MediaBrowser.Api.Images
}
/// <summary>
- /// Class GetUserImage
+ /// Class GetUserImage.
/// </summary>
[Route("/Users/{Id}/Images/{Type}", "GET")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "GET")]
@@ -95,7 +95,7 @@ namespace MediaBrowser.Api.Images
}
/// <summary>
- /// Class ImageService
+ /// Class ImageService.
/// </summary>
public class ImageService : BaseApiService
{
@@ -405,7 +405,6 @@ namespace MediaBrowser.Api.Images
Path = imageResult.Item1,
FileShare = FileShare.Read
-
}).ConfigureAwait(false);
}
@@ -558,6 +557,11 @@ namespace MediaBrowser.Api.Images
// Handle image/png; charset=utf-8
mimeType = mimeType.Split(';').FirstOrDefault();
var userDataPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
+ if (user.ProfileImage != null)
+ {
+ _userManager.ClearProfileImage(user);
+ }
+
user.ProfileImage = new Jellyfin.Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType)));
await _providerManager
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
deleted file mode 100644
index 279fd6ee9b..0000000000
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ /dev/null
@@ -1,1279 +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/LiveTv/ProgressiveFileCopier.cs b/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs
deleted file mode 100644
index 4c608d9a33..0000000000
--- a/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.LiveTv
-{
- public class ProgressiveFileCopier : IAsyncStreamWriter, IHasHeaders
- {
- private readonly ILogger _logger;
- private readonly string _path;
- private readonly Dictionary<string, string> _outputHeaders;
-
- public bool AllowEndOfFile = true;
-
- private readonly IDirectStreamProvider _directStreamProvider;
- private IStreamHelper _streamHelper;
-
- public ProgressiveFileCopier(IStreamHelper streamHelper, string path, Dictionary<string, string> outputHeaders, ILogger logger)
- {
- _path = path;
- _outputHeaders = outputHeaders;
- _logger = logger;
- _streamHelper = streamHelper;
- }
-
- public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, IStreamHelper streamHelper, Dictionary<string, string> outputHeaders, ILogger logger)
- {
- _directStreamProvider = directStreamProvider;
- _outputHeaders = outputHeaders;
- _logger = logger;
- _streamHelper = streamHelper;
- }
-
- public IDictionary<string, string> Headers => _outputHeaders;
-
- public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken)
- {
- if (_directStreamProvider != null)
- {
- await _directStreamProvider.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false);
- return;
- }
-
- var fileOptions = FileOptions.SequentialScan;
-
- // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
- if (Environment.OSVersion.Platform != PlatformID.Win32NT)
- {
- fileOptions |= FileOptions.Asynchronous;
- }
-
- using (var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, fileOptions))
- {
- var emptyReadLimit = AllowEndOfFile ? 20 : 100;
- var eofCount = 0;
- while (eofCount < emptyReadLimit)
- {
- int bytesRead;
- bytesRead = await _streamHelper.CopyToAsync(inputStream, outputStream, cancellationToken).ConfigureAwait(false);
-
- if (bytesRead == 0)
- {
- eofCount++;
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- eofCount = 0;
- }
- }
- }
- }
- }
-}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index cd329c94f9..d703bdb058 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -14,10 +14,6 @@
<Compile Include="..\SharedVersion.cs" />
</ItemGroup>
- <ItemGroup>
- <Folder Include="Library" />
- </ItemGroup>
-
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
deleted file mode 100644
index 2d61299c76..0000000000
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ /dev/null
@@ -1,418 +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 0b53342359..0000000000
--- a/MediaBrowser.Api/Movies/TrailersService.cs
+++ /dev/null
@@ -1,89 +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/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs
deleted file mode 100644
index 7d10c94271..0000000000
--- a/MediaBrowser.Api/Music/InstantMixService.cs
+++ /dev/null
@@ -1,197 +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/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 957e4ae910..84ed5dcac4 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -28,7 +28,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback
{
/// <summary>
- /// Class BaseStreamingService
+ /// Class BaseStreamingService.
/// </summary>
public abstract class BaseStreamingService : BaseApiService
{
@@ -216,7 +216,7 @@ namespace MediaBrowser.Api.Playback
UseShellExecute = false,
// Must consume both stdout and stderr or deadlocks may occur
- //RedirectStandardOutput = true,
+ // RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
@@ -303,6 +303,7 @@ namespace MediaBrowser.Api.Playback
{
StartThrottler(state, transcodingJob);
}
+
Logger.LogDebug("StartFfMpeg() finished successfully");
return transcodingJob;
@@ -608,6 +609,7 @@ namespace MediaBrowser.Api.Playback
{
throw new ArgumentException("Invalid timeseek header");
}
+
int index = value.IndexOf('-');
value = index == -1
? value.Substring(Npt.Length)
@@ -639,8 +641,10 @@ namespace MediaBrowser.Api.Playback
{
throw new ArgumentException("Invalid timeseek header");
}
+
timeFactor /= 60;
}
+
return TimeSpan.FromSeconds(secondsSum).Ticks;
}
@@ -685,7 +689,7 @@ namespace MediaBrowser.Api.Playback
state.User = UserManager.GetUserById(auth.UserId);
}
- //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
+ // if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
// (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
// (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
//{
@@ -716,9 +720,9 @@ namespace MediaBrowser.Api.Playback
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- //var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
+ // var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
// item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
- //if (primaryImage != null)
+ // if (primaryImage != null)
//{
// state.AlbumCoverPath = primaryImage.Path;
//}
@@ -885,7 +889,7 @@ namespace MediaBrowser.Api.Playback
if (transcodingProfile != null)
{
state.EstimateContentLength = transcodingProfile.EstimateContentLength;
- //state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
+ // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
if (state.VideoRequest != null)
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 627421aac6..418cd92b3d 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback.Hls
{
/// <summary>
- /// Class BaseHlsService
+ /// Class BaseHlsService.
/// </summary>
public abstract class BaseHlsService : BaseStreamingService
{
@@ -146,6 +146,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
ApiEntryPoint.Instance.OnTranscodeEndRequest(job);
}
+
return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
@@ -178,7 +179,7 @@ namespace MediaBrowser.Api.Playback.Hls
var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture);
text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
- //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ // text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
return text;
}
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 0a6ed27866..fe5f980b18 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -234,6 +234,7 @@ namespace MediaBrowser.Api.Playback.Hls
Logger.LogDebug("Starting transcoding because segmentGap is {0} and max allowed gap is {1}. requestedIndex={2}", requestedIndex - currentTranscodingIndex.Value, segmentGapRequiringTranscodingChange, requestedIndex);
startTranscoding = true;
}
+
if (startTranscoding)
{
// If the playlist doesn't already exist, startup ffmpeg
@@ -257,7 +258,7 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- //await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
+ // await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
}
else
{
@@ -277,8 +278,8 @@ namespace MediaBrowser.Api.Playback.Hls
}
}
- //Logger.LogInformation("waiting for {0}", segmentPath);
- //while (!File.Exists(segmentPath))
+ // Logger.LogInformation("waiting for {0}", segmentPath);
+ // while (!File.Exists(segmentPath))
//{
// await Task.Delay(50, cancellationToken).ConfigureAwait(false);
//}
@@ -518,6 +519,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
Logger.LogDebug("serving {0} as it's on disk and transcoding stopped", segmentPath);
}
+
cancellationToken.ThrowIfCancellationRequested();
}
else
@@ -717,7 +719,7 @@ namespace MediaBrowser.Api.Playback.Hls
// Having problems in android
return false;
- //return state.VideoRequest.VideoBitRate.HasValue;
+ // return state.VideoRequest.VideoBitRate.HasValue;
}
/// <summary>
@@ -972,7 +974,7 @@ namespace MediaBrowser.Api.Playback.Hls
var queryStringIndex = Request.RawUrl.IndexOf('?');
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
- //if ((Request.UserAgent ?? string.Empty).IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1)
+ // if ((Request.UserAgent ?? string.Empty).IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1)
//{
// queryString = string.Empty;
//}
@@ -1100,7 +1102,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
}
- //args += " -flags -global_header";
+ // args += " -flags -global_header";
}
else
{
@@ -1142,7 +1144,7 @@ namespace MediaBrowser.Api.Playback.Hls
args += " " + keyFrameArg + gopArg;
}
- //args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
+ // args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
@@ -1164,7 +1166,7 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -start_at_zero";
}
- //args += " -flags -global_header";
+ // args += " -flags -global_header";
}
if (!string.IsNullOrEmpty(state.OutputVideoSync))
diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
index 87ccde2e04..8a3d00283f 100644
--- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
+++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
@@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback.Hls
{
/// <summary>
- /// Class GetHlsAudioSegment
+ /// Class GetHlsAudioSegment.
/// </summary>
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
//[Authenticated]
@@ -37,7 +37,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
/// <summary>
- /// Class GetHlsVideoSegment
+ /// Class GetHlsVideoSegment.
/// </summary>
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
[Authenticated]
@@ -66,7 +66,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
/// <summary>
- /// Class GetHlsVideoSegment
+ /// Class GetHlsVideoSegment.
/// </summary>
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
//[Authenticated]
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index aefb3f019b..9562f9953a 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
/// <summary>
- /// Class VideoHlsService
+ /// Class VideoHlsService.
/// </summary>
[Authenticated]
public class VideoHlsService : BaseHlsService
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 2c6534cc08..427d255081 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -28,7 +28,6 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback
{
- [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")]
public class GetPlaybackInfo : IReturn<PlaybackInfoResponse>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -38,24 +37,20 @@ namespace MediaBrowser.Api.Playback
public Guid UserId { get; set; }
}
- [Route("/Items/{Id}/PlaybackInfo", "POST", Summary = "Gets live playback media info for an item")]
public class GetPostedPlaybackInfo : PlaybackInfoRequest, IReturn<PlaybackInfoResponse>
{
}
- [Route("/LiveStreams/Open", "POST", Summary = "Opens a media source")]
public class OpenMediaSource : LiveStreamRequest, IReturn<LiveStreamResponse>
{
}
- [Route("/LiveStreams/Close", "POST", Summary = "Closes a media source")]
public class CloseMediaSource : IReturnVoid
{
[ApiMember(Name = "LiveStreamId", Description = "LiveStreamId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string LiveStreamId { get; set; }
}
- [Route("/Playback/BitrateTest", "GET")]
public class GetBitrateTestBytes
{
[ApiMember(Name = "Size", Description = "Size", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "GET")]
@@ -551,10 +546,12 @@ namespace MediaBrowser.Api.Playback
{
mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
}
+
if (!allowAudioStreamCopy)
{
mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
}
+
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
}
@@ -646,7 +643,6 @@ namespace MediaBrowser.Api.Playback
}
return 1;
-
}).ThenBy(i =>
{
// Let's assume direct streaming a file is just as desirable as direct playing a remote url
@@ -656,7 +652,6 @@ namespace MediaBrowser.Api.Playback
}
return 1;
-
}).ThenBy(i =>
{
return i.Protocol switch
@@ -672,7 +667,6 @@ namespace MediaBrowser.Api.Playback
}
return 1;
-
}).ThenBy(originalList.IndexOf)
.ToArray();
}
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index 34c7986ca5..d51787df27 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback.Progressive
{
/// <summary>
- /// Class GetAudioStream
+ /// Class GetAudioStream.
/// </summary>
[Route("/Audio/{Id}/stream.{Container}", "GET", Summary = "Gets an audio stream")]
[Route("/Audio/{Id}/stream", "GET", Summary = "Gets an audio stream")]
@@ -26,7 +26,7 @@ namespace MediaBrowser.Api.Playback.Progressive
}
/// <summary>
- /// Class AudioService
+ /// Class AudioService.
/// </summary>
// TODO: In order to autheneticate this in the future, Dlna playback will require updating
//[Authenticated]
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index c7bf055fba..2ebf0e420d 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -21,7 +21,7 @@ using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.Playback.Progressive
{
/// <summary>
- /// Class BaseProgressiveStreamingService
+ /// Class BaseProgressiveStreamingService.
/// </summary>
public abstract class BaseProgressiveStreamingService : BaseStreamingService
{
@@ -88,14 +88,17 @@ namespace MediaBrowser.Api.Playback.Progressive
{
return ".ts";
}
+
if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase))
{
return ".ogv";
}
+
if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase))
{
return ".webm";
}
+
if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase))
{
return ".asf";
@@ -111,14 +114,17 @@ namespace MediaBrowser.Api.Playback.Progressive
{
return ".aac";
}
+
if (string.Equals("mp3", audioCodec, StringComparison.OrdinalIgnoreCase))
{
return ".mp3";
}
+
if (string.Equals("vorbis", audioCodec, StringComparison.OrdinalIgnoreCase))
{
return ".ogg";
}
+
if (string.Equals("wma", audioCodec, StringComparison.OrdinalIgnoreCase))
{
return ".wma";
@@ -231,7 +237,7 @@ namespace MediaBrowser.Api.Playback.Progressive
}
//// Not static but transcode cache file exists
- //if (isTranscodeCached && state.VideoRequest == null)
+ // if (isTranscodeCached && state.VideoRequest == null)
//{
// var contentType = state.GetMimeType(outputPath);
diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
index a53b848f9e..b70fff128b 100644
--- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
+++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
@@ -23,6 +23,7 @@ namespace MediaBrowser.Api.Playback.Progressive
private long _bytesWritten = 0;
public long StartPosition { get; set; }
+
public bool AllowEndOfFile = true;
private readonly IDirectStreamProvider _directStreamProvider;
@@ -96,8 +97,8 @@ namespace MediaBrowser.Api.Playback.Progressive
bytesRead = await CopyToInternalAsyncWithSyncRead(inputStream, outputStream, cancellationToken).ConfigureAwait(false);
}
- //var position = fs.Position;
- //_logger.LogDebug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
+ // var position = fs.Position;
+ // _logger.LogDebug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
if (bytesRead == 0)
{
@@ -105,6 +106,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
eofCount++;
}
+
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
else
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 4de81655ce..c3f6b905cb 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback.Progressive
{
/// <summary>
- /// Class GetVideoStream
+ /// Class GetVideoStream.
/// </summary>
[Route("/Videos/{Id}/stream.mpegts", "GET")]
[Route("/Videos/{Id}/stream.ts", "GET")]
@@ -59,11 +59,10 @@ namespace MediaBrowser.Api.Playback.Progressive
[Route("/Videos/{Id}/stream", "HEAD")]
public class GetVideoStream : VideoStreamRequest
{
-
}
/// <summary>
- /// Class VideoService
+ /// Class VideoService.
/// </summary>
// TODO: In order to autheneticate this in the future, Dlna playback will require updating
//[Authenticated]
diff --git a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
index 3b8b299957..7e2e337ad1 100644
--- a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
+++ b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
@@ -8,17 +8,17 @@ using MediaBrowser.Model.Services;
namespace MediaBrowser.Api.Playback
{
/// <summary>
- /// Class StaticRemoteStreamWriter
+ /// Class StaticRemoteStreamWriter.
/// </summary>
public class StaticRemoteStreamWriter : IAsyncStreamWriter, IHasHeaders
{
/// <summary>
- /// The _input stream
+ /// The _input stream.
/// </summary>
private readonly HttpResponseInfo _response;
/// <summary>
- /// The _options
+ /// The _options.
/// </summary>
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index 9ba8eda91f..67c334e489 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Model.Services;
namespace MediaBrowser.Api.Playback
{
/// <summary>
- /// Class StreamRequest
+ /// Class StreamRequest.
/// </summary>
public class StreamRequest : BaseEncodingJobOptions
{
@@ -12,11 +12,15 @@ namespace MediaBrowser.Api.Playback
public string DeviceProfileId { get; set; }
public string Params { get; set; }
+
public string PlaySessionId { get; set; }
+
public string Tag { get; set; }
+
public string SegmentContainer { get; set; }
public int? SegmentLength { get; set; }
+
public int? MinSegments { get; set; }
}
diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs
index a3b319d44b..d5d78cf37a 100644
--- a/MediaBrowser.Api/Playback/UniversalAudioService.cs
+++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs
@@ -37,10 +37,13 @@ namespace MediaBrowser.Api.Playback
public string DeviceId { get; set; }
public Guid UserId { get; set; }
+
public string AudioCodec { get; set; }
+
public string Container { get; set; }
public int? MaxAudioChannels { get; set; }
+
public int? TranscodingAudioChannels { get; set; }
public long? MaxStreamingBitrate { get; set; }
@@ -49,12 +52,17 @@ namespace MediaBrowser.Api.Playback
public long? StartTimeTicks { get; set; }
public string TranscodingContainer { get; set; }
+
public string TranscodingProtocol { get; set; }
+
public int? MaxAudioSampleRate { get; set; }
+
public int? MaxAudioBitDepth { get; set; }
public bool EnableRedirection { get; set; }
+
public bool EnableRemoteMedia { get; set; }
+
public bool BreakOnNonKeyFrames { get; set; }
public BaseUniversalRequest()
@@ -114,16 +122,27 @@ namespace MediaBrowser.Api.Playback
}
protected IHttpClient HttpClient { get; private set; }
+
protected IUserManager UserManager { get; private set; }
+
protected ILibraryManager LibraryManager { get; private set; }
+
protected IIsoManager IsoManager { get; private set; }
+
protected IMediaEncoder MediaEncoder { get; private set; }
+
protected IFileSystem FileSystem { get; private set; }
+
protected IDlnaManager DlnaManager { get; private set; }
+
protected IDeviceManager DeviceManager { get; private set; }
+
protected IMediaSourceManager MediaSourceManager { get; private set; }
+
protected IJsonSerializer JsonSerializer { get; private set; }
+
protected IAuthorizationContext AuthorizationContext { get; private set; }
+
protected INetworkManager NetworkManager { get; private set; }
public Task<object> Get(GetUniversalAudioStream request)
@@ -259,7 +278,6 @@ namespace MediaBrowser.Api.Playback
UserId = request.UserId,
DeviceProfile = deviceProfile,
MediaSourceId = request.MediaSourceId
-
}).ConfigureAwait(false);
var mediaSource = playbackInfoResult.MediaSources[0];
@@ -329,6 +347,7 @@ namespace MediaBrowser.Api.Playback
{
return await service.Head(newRequest).ConfigureAwait(false);
}
+
return await service.Get(newRequest).ConfigureAwait(false);
}
else
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
deleted file mode 100644
index e08a8482e0..0000000000
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
+++ /dev/null
@@ -1,234 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Tasks;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.ScheduledTasks
-{
- /// <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/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
index 14b9b3618b..25dd39f2de 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
@@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.ScheduledTasks
{
/// <summary>
- /// Class ScheduledTasksWebSocketListener
+ /// Class ScheduledTasksWebSocketListener.
/// </summary>
public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>
{
diff --git a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs
index 175984575d..2400d6defe 100644
--- a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs
@@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Sessions
{
/// <summary>
- /// Class SessionInfoWebSocketListener
+ /// Class SessionInfoWebSocketListener.
/// </summary>
public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState>
{
@@ -19,7 +19,7 @@ namespace MediaBrowser.Api.Sessions
protected override string Name => "Sessions";
/// <summary>
- /// The _kernel
+ /// The _kernel.
/// </summary>
private readonly ISessionManager _sessionManager;
diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs
deleted file mode 100644
index dcd22280a6..0000000000
--- a/MediaBrowser.Api/SimilarItemsHelper.cs
+++ /dev/null
@@ -1,223 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-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 BaseGetSimilarItemsFromItem
- /// </summary>
- public class BaseGetSimilarItemsFromItem : BaseGetSimilarItems
- {
- /// <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 string ExcludeArtistIds { get; set; }
- }
-
- public class BaseGetSimilarItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [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>
- /// 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>
- /// 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>
- /// Class SimilarItemsHelper
- /// </summary>
- public static class SimilarItemsHelper
- {
- internal static QueryResult<BaseItemDto> GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
- {
- 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 query = new InternalItemsQuery(user)
- {
- IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
- Recursive = true,
- DtoOptions = dtoOptions
- };
-
- // ExcludeArtistIds
- if (!string.IsNullOrEmpty(request.ExcludeArtistIds))
- {
- query.ExcludeArtistIds = BaseApiService.GetGuids(request.ExcludeArtistIds);
- }
-
- var inputItems = libraryManager.GetItemList(query);
-
- var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
- .ToList();
-
- var returnItems = items;
-
- if (request.Limit.HasValue)
- {
- returnItems = returnItems.Take(request.Limit.Value).ToList();
- }
-
- var dtos = dtoService.GetBaseItemDtos(returnItems, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- Items = dtos,
-
- TotalRecordCount = items.Count
- };
- }
-
- /// <summary>
- /// Gets the similaritems.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="inputItems">The input items.</param>
- /// <param name="getSimilarityScore">The get similarity score.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- internal static IEnumerable<BaseItem> GetSimilaritems(BaseItem item, ILibraryManager libraryManager, IEnumerable<BaseItem> inputItems, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
- {
- var itemId = item.Id;
- inputItems = inputItems.Where(i => i.Id != itemId);
- var itemPeople = libraryManager.GetPeople(item);
- var allPeople = libraryManager.GetPeople(new InternalPeopleQuery
- {
- AppearsInItemId = item.Id
- });
-
- return inputItems.Select(i => new Tuple<BaseItem, int>(i, getSimilarityScore(item, itemPeople, allPeople, i)))
- .Where(i => i.Item2 > 2)
- .OrderByDescending(i => i.Item2)
- .Select(i => i.Item1);
- }
-
- private static IEnumerable<string> GetTags(BaseItem item)
- {
- return item.Tags;
- }
-
- /// <summary>
- /// Gets the similiarity 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>
- internal static int GetSimiliarityScore(BaseItem item1, List<PersonInfo> item1People, List<PersonInfo> allPeople, BaseItem item2)
- {
- var points = 0;
-
- if (!string.IsNullOrEmpty(item1.OfficialRating) && string.Equals(item1.OfficialRating, item2.OfficialRating, StringComparison.OrdinalIgnoreCase))
- {
- points += 10;
- }
-
- // Find common genres
- points += item1.Genres.Where(i => item2.Genres.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10);
-
- // Find common tags
- points += GetTags(item1).Where(i => GetTags(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10);
-
- // Find common studios
- points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 3);
-
- var item2PeopleNames = allPeople.Where(i => i.ItemId == item2.Id)
- .Select(i => i.Name)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .DistinctNames()
- .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- points += item1People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i =>
- {
- if (string.Equals(i.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase))
- {
- return 5;
- }
- if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
- if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
- if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
- if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase))
- {
- return 2;
- }
-
- return 1;
- });
-
- if (item1.ProductionYear.HasValue && item2.ProductionYear.HasValue)
- {
- var diff = Math.Abs(item1.ProductionYear.Value - item2.ProductionYear.Value);
-
- // Add if they came out within the same decade
- if (diff < 10)
- {
- points += 2;
- }
-
- // And more if within five years
- if (diff < 5)
- {
- points += 2;
- }
- }
-
- return points;
- }
-
- }
-}
diff --git a/MediaBrowser.Api/SyncPlay/SyncPlayService.cs b/MediaBrowser.Api/SyncPlay/SyncPlayService.cs
index 1e14ea552c..daa1b521f4 100644
--- a/MediaBrowser.Api/SyncPlay/SyncPlayService.cs
+++ b/MediaBrowser.Api/SyncPlay/SyncPlayService.cs
@@ -11,93 +11,66 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.SyncPlay
{
- [Route("/SyncPlay/{SessionId}/NewGroup", "POST", Summary = "Create a new SyncPlay group")]
+ [Route("/SyncPlay/New", "POST", Summary = "Create a new SyncPlay group")]
[Authenticated]
- public class SyncPlayNewGroup : IReturnVoid
+ public class SyncPlayNew : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/JoinGroup", "POST", Summary = "Join an existing SyncPlay group")]
+ [Route("/SyncPlay/Join", "POST", Summary = "Join an existing SyncPlay group")]
[Authenticated]
- public class SyncPlayJoinGroup : IReturnVoid
+ public class SyncPlayJoin : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
-
/// <summary>
/// Gets or sets the Group id.
/// </summary>
/// <value>The Group id to join.</value>
[ApiMember(Name = "GroupId", Description = "Group Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string GroupId { get; set; }
-
- /// <summary>
- /// Gets or sets the playing item id.
- /// </summary>
- /// <value>The client's currently playing item id.</value>
- [ApiMember(Name = "PlayingItemId", Description = "Client's playing item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlayingItemId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/LeaveGroup", "POST", Summary = "Leave joined SyncPlay group")]
+ [Route("/SyncPlay/Leave", "POST", Summary = "Leave joined SyncPlay group")]
[Authenticated]
- public class SyncPlayLeaveGroup : IReturnVoid
+ public class SyncPlayLeave : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/ListGroups", "POST", Summary = "List SyncPlay groups")]
+ [Route("/SyncPlay/List", "GET", Summary = "List SyncPlay groups")]
[Authenticated]
- public class SyncPlayListGroups : IReturnVoid
+ public class SyncPlayList : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
-
/// <summary>
/// Gets or sets the filter item id.
/// </summary>
/// <value>The filter item id.</value>
- [ApiMember(Name = "FilterItemId", Description = "Filter by item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "FilterItemId", Description = "Filter by item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string FilterItemId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/PlayRequest", "POST", Summary = "Request play in SyncPlay group")]
+ [Route("/SyncPlay/Play", "POST", Summary = "Request play in SyncPlay group")]
[Authenticated]
- public class SyncPlayPlayRequest : IReturnVoid
+ public class SyncPlayPlay : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/PauseRequest", "POST", Summary = "Request pause in SyncPlay group")]
+ [Route("/SyncPlay/Pause", "POST", Summary = "Request pause in SyncPlay group")]
[Authenticated]
- public class SyncPlayPauseRequest : IReturnVoid
+ public class SyncPlayPause : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
}
- [Route("/SyncPlay/{SessionId}/SeekRequest", "POST", Summary = "Request seek in SyncPlay group")]
+ [Route("/SyncPlay/Seek", "POST", Summary = "Request seek in SyncPlay group")]
[Authenticated]
- public class SyncPlaySeekRequest : IReturnVoid
+ public class SyncPlaySeek : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
-
[ApiMember(Name = "PositionTicks", IsRequired = true, DataType = "long", ParameterType = "query", Verb = "POST")]
public long PositionTicks { get; set; }
}
- [Route("/SyncPlay/{SessionId}/BufferingRequest", "POST", Summary = "Request group wait in SyncPlay group while buffering")]
+ [Route("/SyncPlay/Buffering", "POST", Summary = "Request group wait in SyncPlay group while buffering")]
[Authenticated]
- public class SyncPlayBufferingRequest : IReturnVoid
+ public class SyncPlayBuffering : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
-
/// <summary>
/// Gets or sets the date used to pin PositionTicks in time.
/// </summary>
@@ -109,20 +82,17 @@ namespace MediaBrowser.Api.SyncPlay
public long PositionTicks { get; set; }
/// <summary>
- /// Gets or sets whether this is a buffering or a buffering-done request.
+ /// Gets or sets whether this is a buffering or a ready request.
/// </summary>
/// <value><c>true</c> if buffering is complete; <c>false</c> otherwise.</value>
[ApiMember(Name = "BufferingDone", IsRequired = true, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool BufferingDone { get; set; }
}
- [Route("/SyncPlay/{SessionId}/UpdatePing", "POST", Summary = "Update session ping")]
+ [Route("/SyncPlay/Ping", "POST", Summary = "Update session ping")]
[Authenticated]
- public class SyncPlayUpdatePing : IReturnVoid
+ public class SyncPlayPing : IReturnVoid
{
- [ApiMember(Name = "SessionId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string SessionId { get; set; }
-
[ApiMember(Name = "Ping", IsRequired = true, DataType = "double", ParameterType = "query", Verb = "POST")]
public double Ping { get; set; }
}
@@ -158,7 +128,7 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayNewGroup request)
+ public void Post(SyncPlayNew request)
{
var currentSession = GetSession(_sessionContext);
_syncPlayManager.NewGroup(currentSession, CancellationToken.None);
@@ -168,30 +138,20 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayJoinGroup request)
+ public void Post(SyncPlayJoin request)
{
var currentSession = GetSession(_sessionContext);
Guid groupId;
- Guid playingItemId = Guid.Empty;
-
if (!Guid.TryParse(request.GroupId, out groupId))
{
Logger.LogError("JoinGroup: {0} is not a valid format for GroupId. Ignoring request.", request.GroupId);
return;
}
- // Both null and empty strings mean that client isn't playing anything
- if (!string.IsNullOrEmpty(request.PlayingItemId) && !Guid.TryParse(request.PlayingItemId, out playingItemId))
- {
- Logger.LogError("JoinGroup: {0} is not a valid format for PlayingItemId. Ignoring request.", request.PlayingItemId);
- return;
- }
-
var joinRequest = new JoinGroupRequest()
{
- GroupId = groupId,
- PlayingItemId = playingItemId
+ GroupId = groupId
};
_syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None);
@@ -201,7 +161,7 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayLeaveGroup request)
+ public void Post(SyncPlayLeave request)
{
var currentSession = GetSession(_sessionContext);
_syncPlayManager.LeaveGroup(currentSession, CancellationToken.None);
@@ -212,7 +172,7 @@ namespace MediaBrowser.Api.SyncPlay
/// </summary>
/// <param name="request">The request.</param>
/// <value>The requested list of groups.</value>
- public List<GroupInfoView> Post(SyncPlayListGroups request)
+ public List<GroupInfoView> Get(SyncPlayList request)
{
var currentSession = GetSession(_sessionContext);
var filterItemId = Guid.Empty;
@@ -229,7 +189,7 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayPlayRequest request)
+ public void Post(SyncPlayPlay request)
{
var currentSession = GetSession(_sessionContext);
var syncPlayRequest = new PlaybackRequest()
@@ -243,7 +203,7 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayPauseRequest request)
+ public void Post(SyncPlayPause request)
{
var currentSession = GetSession(_sessionContext);
var syncPlayRequest = new PlaybackRequest()
@@ -257,7 +217,7 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlaySeekRequest request)
+ public void Post(SyncPlaySeek request)
{
var currentSession = GetSession(_sessionContext);
var syncPlayRequest = new PlaybackRequest()
@@ -272,12 +232,12 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayBufferingRequest request)
+ public void Post(SyncPlayBuffering request)
{
var currentSession = GetSession(_sessionContext);
var syncPlayRequest = new PlaybackRequest()
{
- Type = request.BufferingDone ? PlaybackRequestType.BufferingDone : PlaybackRequestType.Buffering,
+ Type = request.BufferingDone ? PlaybackRequestType.Ready : PlaybackRequestType.Buffer,
When = DateTime.Parse(request.When),
PositionTicks = request.PositionTicks
};
@@ -288,12 +248,12 @@ namespace MediaBrowser.Api.SyncPlay
/// Handles the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(SyncPlayUpdatePing request)
+ public void Post(SyncPlayPing request)
{
var currentSession = GetSession(_sessionContext);
var syncPlayRequest = new PlaybackRequest()
{
- Type = PlaybackRequestType.UpdatePing,
+ Type = PlaybackRequestType.Ping,
Ping = Convert.ToInt64(request.Ping)
};
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
index 8e4860be4b..39976371a9 100644
--- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
+++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
@@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.System
{
/// <summary>
- /// Class SessionInfoWebSocketListener
+ /// Class SessionInfoWebSocketListener.
/// </summary>
public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState>
{
@@ -19,7 +19,7 @@ namespace MediaBrowser.Api.System
protected override string Name => "ActivityLogEntry";
/// <summary>
- /// The _kernel
+ /// The _kernel.
/// </summary>
private readonly IActivityManager _activityManager;
diff --git a/MediaBrowser.Api/TranscodingJob.cs b/MediaBrowser.Api/TranscodingJob.cs
index 8c24e3ce18..bfc311a272 100644
--- a/MediaBrowser.Api/TranscodingJob.cs
+++ b/MediaBrowser.Api/TranscodingJob.cs
@@ -32,6 +32,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The path.</value>
public MediaSourceInfo MediaSource { get; set; }
+
public string Path { get; set; }
/// <summary>
/// Gets or sets the type.
@@ -43,6 +44,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The process.</value>
public Process Process { get; set; }
+
public ILogger Logger { get; private set; }
/// <summary>
/// Gets or sets the active request count.
@@ -62,18 +64,23 @@ namespace MediaBrowser.Api
public object ProcessLock = new object();
public bool HasExited { get; set; }
+
public bool IsUserPaused { get; set; }
public string Id { get; set; }
public float? Framerate { get; set; }
+
public double? CompletionPercentage { get; set; }
public long? BytesDownloaded { get; set; }
+
public long? BytesTranscoded { get; set; }
+
public int? BitRate { get; set; }
public long? TranscodingPositionTicks { get; set; }
+
public long? DownloadPositionTicks { get; set; }
public TranscodingThrottler TranscodingThrottler { get; set; }
@@ -81,6 +88,7 @@ namespace MediaBrowser.Api
private readonly object _timerLock = new object();
public DateTime LastPingDate { get; set; }
+
public int PingTimeout { get; set; }
public TranscodingJob(ILogger logger)
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
deleted file mode 100644
index bef91d54df..0000000000
--- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 a1ec084679..0000000000
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ /dev/null
@@ -1,388 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 7561b5c892..0000000000
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ /dev/null
@@ -1,475 +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 1fa272a5f7..0000000000
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 49d534c364..0000000000
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ /dev/null
@@ -1,514 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
deleted file mode 100644
index e9caca14aa..0000000000
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ /dev/null
@@ -1,124 +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
-{
- [Route("/MusicGenres", "GET", Summary = "Gets all music genres from a given item, folder, or the entire library")]
- public class GetMusicGenres : GetItemsByName
- {
- }
-
- [Route("/MusicGenres/{Name}", "GET", Summary = "Gets a music genre, by name")]
- public class GetMusicGenre : 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; }
- }
-
- [Authenticated]
- public class MusicGenresService : BaseItemsByNameService<MusicGenre>
- {
- public MusicGenresService(
- ILogger<MusicGenresService> 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(GetMusicGenre 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(GetMusicGenre request)
- {
- var dtoOptions = GetDtoOptions(AuthorizationContext, request);
-
- var item = GetMusicGenre(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(GetMusicGenres request)
- {
- var result = GetResultSlim(request);
-
- return ToOptimizedResult(result);
- }
-
- protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query)
- {
- return LibraryManager.GetMusicGenres(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/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
deleted file mode 100644
index 3204e5219f..0000000000
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 ab231626bb..0000000000
--- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs
+++ /dev/null
@@ -1,456 +0,0 @@
-using System;
-using System.Globalization;
-using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Session;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 683ce5d09d..0000000000
--- a/MediaBrowser.Api/UserLibrary/StudiosService.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 f758528859..0000000000
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ /dev/null
@@ -1,575 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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 0fffb06223..0000000000
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ /dev/null
@@ -1,146 +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 d023ee90ab..0000000000
--- a/MediaBrowser.Api/UserLibrary/YearsService.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.UserLibrary
-{
- /// <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));
- }
- }
-}