From f5f890e68562e55d4bed16c454c4b4305152b296 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 31 Jan 2023 12:18:10 +0100 Subject: Migrate to file-scoped namespaces --- Jellyfin.Api/Controllers/LiveTvController.cs | 2205 +++++++++++++------------- 1 file changed, 1102 insertions(+), 1103 deletions(-) (limited to 'Jellyfin.Api/Controllers/LiveTvController.cs') diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 5228e0bab..21b424346 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -35,1200 +35,1199 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -namespace Jellyfin.Api.Controllers +namespace Jellyfin.Api.Controllers; + +/// +/// Live tv controller. +/// +public class LiveTvController : BaseJellyfinApiController { + private readonly ILiveTvManager _liveTvManager; + private readonly IUserManager _userManager; + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILibraryManager _libraryManager; + private readonly IDtoService _dtoService; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly IConfigurationManager _configurationManager; + private readonly TranscodingJobHelper _transcodingJobHelper; + private readonly ISessionManager _sessionManager; + /// - /// Live tv controller. + /// Initializes a new instance of the class. /// - public class LiveTvController : BaseJellyfinApiController + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the class. + /// Instance of the interface. + public LiveTvController( + ILiveTvManager liveTvManager, + IUserManager userManager, + IHttpClientFactory httpClientFactory, + ILibraryManager libraryManager, + IDtoService dtoService, + IMediaSourceManager mediaSourceManager, + IConfigurationManager configurationManager, + TranscodingJobHelper transcodingJobHelper, + ISessionManager sessionManager) { - private readonly ILiveTvManager _liveTvManager; - private readonly IUserManager _userManager; - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILibraryManager _libraryManager; - private readonly IDtoService _dtoService; - private readonly IMediaSourceManager _mediaSourceManager; - private readonly IConfigurationManager _configurationManager; - private readonly TranscodingJobHelper _transcodingJobHelper; - private readonly ISessionManager _sessionManager; - - /// - /// Initializes a new instance of the class. - /// - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the class. - /// Instance of the interface. - public LiveTvController( - ILiveTvManager liveTvManager, - IUserManager userManager, - IHttpClientFactory httpClientFactory, - ILibraryManager libraryManager, - IDtoService dtoService, - IMediaSourceManager mediaSourceManager, - IConfigurationManager configurationManager, - TranscodingJobHelper transcodingJobHelper, - ISessionManager sessionManager) - { - _liveTvManager = liveTvManager; - _userManager = userManager; - _httpClientFactory = httpClientFactory; - _libraryManager = libraryManager; - _dtoService = dtoService; - _mediaSourceManager = mediaSourceManager; - _configurationManager = configurationManager; - _transcodingJobHelper = transcodingJobHelper; - _sessionManager = sessionManager; - } + _liveTvManager = liveTvManager; + _userManager = userManager; + _httpClientFactory = httpClientFactory; + _libraryManager = libraryManager; + _dtoService = dtoService; + _mediaSourceManager = mediaSourceManager; + _configurationManager = configurationManager; + _transcodingJobHelper = transcodingJobHelper; + _sessionManager = sessionManager; + } - /// - /// Gets available live tv services. - /// - /// Available live tv services returned. - /// - /// An containing the available live tv services. - /// - [HttpGet("Info")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetLiveTvInfo() - { - return _liveTvManager.GetLiveTvInfo(CancellationToken.None); - } + /// + /// Gets available live tv services. + /// + /// Available live tv services returned. + /// + /// An containing the available live tv services. + /// + [HttpGet("Info")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult GetLiveTvInfo() + { + return _liveTvManager.GetLiveTvInfo(CancellationToken.None); + } - /// - /// Gets available live tv channels. - /// - /// Optional. Filter by channel type. - /// Optional. Filter by user and attach user data. - /// Optional. The record index to start at. All items with a lower index will be dropped from the results. - /// Optional. Filter for movies. - /// Optional. Filter for series. - /// Optional. Filter for news. - /// Optional. Filter for kids. - /// Optional. Filter for sports. - /// Optional. The maximum number of records to return. - /// Optional. Filter by channels that are favorites, or not. - /// Optional. Filter by channels that are liked, or not. - /// Optional. Filter by channels that are disliked, or not. - /// Optional. Include image information in output. - /// Optional. The max number of images to return, per image type. - /// "Optional. The image types to include in the output. - /// Optional. Specify additional fields of information to return in the output. - /// Optional. Include user data. - /// Optional. Key to sort by. - /// Optional. Sort order. - /// Optional. Incorporate favorite and like status into channel sorting. - /// Optional. Adds current program info to each channel. - /// Available live tv channels returned. - /// - /// An containing the resulting available live tv channels. - /// - [HttpGet("Channels")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult> GetLiveTvChannels( - [FromQuery] ChannelType? type, - [FromQuery] Guid? userId, - [FromQuery] int? startIndex, - [FromQuery] bool? isMovie, - [FromQuery] bool? isSeries, - [FromQuery] bool? isNews, - [FromQuery] bool? isKids, - [FromQuery] bool? isSports, - [FromQuery] int? limit, - [FromQuery] bool? isFavorite, - [FromQuery] bool? isLiked, - [FromQuery] bool? isDisliked, - [FromQuery] bool? enableImages, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool? enableUserData, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, - [FromQuery] SortOrder? sortOrder, - [FromQuery] bool enableFavoriteSorting = false, - [FromQuery] bool addCurrentProgram = true) - { - var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(User) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - - var channelResult = _liveTvManager.GetInternalChannels( - new LiveTvChannelQuery - { - ChannelType = type, - UserId = userId ?? Guid.Empty, - StartIndex = startIndex, - Limit = limit, - IsFavorite = isFavorite, - IsLiked = isLiked, - IsDisliked = isDisliked, - EnableFavoriteSorting = enableFavoriteSorting, - IsMovie = isMovie, - IsSeries = isSeries, - IsNews = isNews, - IsKids = isKids, - IsSports = isSports, - SortBy = sortBy, - SortOrder = sortOrder ?? SortOrder.Ascending, - AddCurrentProgram = addCurrentProgram - }, - dtoOptions, - CancellationToken.None); - - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); - - var fieldsList = dtoOptions.Fields.ToList(); - fieldsList.Remove(ItemFields.CanDelete); - fieldsList.Remove(ItemFields.CanDownload); - fieldsList.Remove(ItemFields.DisplayPreferencesId); - fieldsList.Remove(ItemFields.Etag); - dtoOptions.Fields = fieldsList.ToArray(); - dtoOptions.AddCurrentProgram = addCurrentProgram; - - var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, dtoOptions, user); - return new QueryResult( - startIndex, - channelResult.TotalRecordCount, - returnArray); - } + /// + /// Gets available live tv channels. + /// + /// Optional. Filter by channel type. + /// Optional. Filter by user and attach user data. + /// Optional. The record index to start at. All items with a lower index will be dropped from the results. + /// Optional. Filter for movies. + /// Optional. Filter for series. + /// Optional. Filter for news. + /// Optional. Filter for kids. + /// Optional. Filter for sports. + /// Optional. The maximum number of records to return. + /// Optional. Filter by channels that are favorites, or not. + /// Optional. Filter by channels that are liked, or not. + /// Optional. Filter by channels that are disliked, or not. + /// Optional. Include image information in output. + /// Optional. The max number of images to return, per image type. + /// "Optional. The image types to include in the output. + /// Optional. Specify additional fields of information to return in the output. + /// Optional. Include user data. + /// Optional. Key to sort by. + /// Optional. Sort order. + /// Optional. Incorporate favorite and like status into channel sorting. + /// Optional. Adds current program info to each channel. + /// Available live tv channels returned. + /// + /// An containing the resulting available live tv channels. + /// + [HttpGet("Channels")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult> GetLiveTvChannels( + [FromQuery] ChannelType? type, + [FromQuery] Guid? userId, + [FromQuery] int? startIndex, + [FromQuery] bool? isMovie, + [FromQuery] bool? isSeries, + [FromQuery] bool? isNews, + [FromQuery] bool? isKids, + [FromQuery] bool? isSports, + [FromQuery] int? limit, + [FromQuery] bool? isFavorite, + [FromQuery] bool? isLiked, + [FromQuery] bool? isDisliked, + [FromQuery] bool? enableImages, + [FromQuery] int? imageTypeLimit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, + [FromQuery] bool? enableUserData, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery] SortOrder? sortOrder, + [FromQuery] bool enableFavoriteSorting = false, + [FromQuery] bool addCurrentProgram = true) + { + var dtoOptions = new DtoOptions { Fields = fields } + .AddClientFields(User) + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - /// - /// Gets a live tv channel. - /// - /// Channel id. - /// Optional. Attach user data. - /// Live tv channel returned. - /// An containing the live tv channel. - [HttpGet("Channels/{channelId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetChannel([FromRoute, Required] Guid channelId, [FromQuery] Guid? userId) - { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); - var item = channelId.Equals(default) - ? _libraryManager.GetUserRootFolder() - : _libraryManager.GetItemById(channelId); - - var dtoOptions = new DtoOptions() - .AddClientFields(User); - return _dtoService.GetBaseItemDto(item, dtoOptions, user); - } + var channelResult = _liveTvManager.GetInternalChannels( + new LiveTvChannelQuery + { + ChannelType = type, + UserId = userId ?? Guid.Empty, + StartIndex = startIndex, + Limit = limit, + IsFavorite = isFavorite, + IsLiked = isLiked, + IsDisliked = isDisliked, + EnableFavoriteSorting = enableFavoriteSorting, + IsMovie = isMovie, + IsSeries = isSeries, + IsNews = isNews, + IsKids = isKids, + IsSports = isSports, + SortBy = sortBy, + SortOrder = sortOrder ?? SortOrder.Ascending, + AddCurrentProgram = addCurrentProgram + }, + dtoOptions, + CancellationToken.None); + + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); + + var fieldsList = dtoOptions.Fields.ToList(); + fieldsList.Remove(ItemFields.CanDelete); + fieldsList.Remove(ItemFields.CanDownload); + fieldsList.Remove(ItemFields.DisplayPreferencesId); + fieldsList.Remove(ItemFields.Etag); + dtoOptions.Fields = fieldsList.ToArray(); + dtoOptions.AddCurrentProgram = addCurrentProgram; + + var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, dtoOptions, user); + return new QueryResult( + startIndex, + channelResult.TotalRecordCount, + returnArray); + } - /// - /// Gets live tv recordings. - /// - /// Optional. Filter by channel id. - /// Optional. Filter by user and attach user data. - /// Optional. The record index to start at. All items with a lower index will be dropped from the results. - /// Optional. The maximum number of records to return. - /// Optional. Filter by recording status. - /// Optional. Filter by recordings that are in progress, or not. - /// Optional. Filter by recordings belonging to a series timer. - /// Optional. Include image information in output. - /// Optional. The max number of images to return, per image type. - /// Optional. The image types to include in the output. - /// Optional. Specify additional fields of information to return in the output. - /// Optional. Include user data. - /// Optional. Filter for movies. - /// Optional. Filter for series. - /// Optional. Filter for kids. - /// Optional. Filter for sports. - /// Optional. Filter for news. - /// Optional. Filter for is library item. - /// Optional. Return total record count. - /// Live tv recordings returned. - /// An containing the live tv recordings. - [HttpGet("Recordings")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult> GetRecordings( - [FromQuery] string? channelId, - [FromQuery] Guid? userId, - [FromQuery] int? startIndex, - [FromQuery] int? limit, - [FromQuery] RecordingStatus? status, - [FromQuery] bool? isInProgress, - [FromQuery] string? seriesTimerId, - [FromQuery] bool? enableImages, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool? enableUserData, - [FromQuery] bool? isMovie, - [FromQuery] bool? isSeries, - [FromQuery] bool? isKids, - [FromQuery] bool? isSports, - [FromQuery] bool? isNews, - [FromQuery] bool? isLibraryItem, - [FromQuery] bool enableTotalRecordCount = true) - { - var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(User) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - - return _liveTvManager.GetRecordings( - new RecordingQuery - { - ChannelId = channelId, - UserId = userId ?? Guid.Empty, - StartIndex = startIndex, - Limit = limit, - Status = status, - SeriesTimerId = seriesTimerId, - IsInProgress = isInProgress, - EnableTotalRecordCount = enableTotalRecordCount, - IsMovie = isMovie, - IsNews = isNews, - IsSeries = isSeries, - IsKids = isKids, - IsSports = isSports, - IsLibraryItem = isLibraryItem, - Fields = fields, - ImageTypeLimit = imageTypeLimit, - EnableImages = enableImages - }, - dtoOptions); - } + /// + /// Gets a live tv channel. + /// + /// Channel id. + /// Optional. Attach user data. + /// Live tv channel returned. + /// An containing the live tv channel. + [HttpGet("Channels/{channelId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult GetChannel([FromRoute, Required] Guid channelId, [FromQuery] Guid? userId) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); + var item = channelId.Equals(default) + ? _libraryManager.GetUserRootFolder() + : _libraryManager.GetItemById(channelId); + + var dtoOptions = new DtoOptions() + .AddClientFields(User); + return _dtoService.GetBaseItemDto(item, dtoOptions, user); + } - /// - /// Gets live tv recording series. - /// - /// Optional. Filter by channel id. - /// Optional. Filter by user and attach user data. - /// Optional. Filter by recording group. - /// Optional. The record index to start at. All items with a lower index will be dropped from the results. - /// Optional. The maximum number of records to return. - /// Optional. Filter by recording status. - /// Optional. Filter by recordings that are in progress, or not. - /// Optional. Filter by recordings belonging to a series timer. - /// Optional. Include image information in output. - /// Optional. The max number of images to return, per image type. - /// Optional. The image types to include in the output. - /// Optional. Specify additional fields of information to return in the output. - /// Optional. Include user data. - /// Optional. Return total record count. - /// Live tv recordings returned. - /// An containing the live tv recordings. - [HttpGet("Recordings/Series")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - [Obsolete("This endpoint is obsolete.")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "channelId", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "groupId", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "startIndex", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "limit", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "status", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isInProgress", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "seriesTimerId", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableImages", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageTypeLimit", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableImageTypes", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "fields", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableUserData", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableTotalRecordCount", Justification = "Imported from ServiceStack")] - public ActionResult> GetRecordingsSeries( - [FromQuery] string? channelId, - [FromQuery] Guid? userId, - [FromQuery] string? groupId, - [FromQuery] int? startIndex, - [FromQuery] int? limit, - [FromQuery] RecordingStatus? status, - [FromQuery] bool? isInProgress, - [FromQuery] string? seriesTimerId, - [FromQuery] bool? enableImages, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool? enableUserData, - [FromQuery] bool enableTotalRecordCount = true) - { - return new QueryResult(); - } + /// + /// Gets live tv recordings. + /// + /// Optional. Filter by channel id. + /// Optional. Filter by user and attach user data. + /// Optional. The record index to start at. All items with a lower index will be dropped from the results. + /// Optional. The maximum number of records to return. + /// Optional. Filter by recording status. + /// Optional. Filter by recordings that are in progress, or not. + /// Optional. Filter by recordings belonging to a series timer. + /// Optional. Include image information in output. + /// Optional. The max number of images to return, per image type. + /// Optional. The image types to include in the output. + /// Optional. Specify additional fields of information to return in the output. + /// Optional. Include user data. + /// Optional. Filter for movies. + /// Optional. Filter for series. + /// Optional. Filter for kids. + /// Optional. Filter for sports. + /// Optional. Filter for news. + /// Optional. Filter for is library item. + /// Optional. Return total record count. + /// Live tv recordings returned. + /// An containing the live tv recordings. + [HttpGet("Recordings")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult> GetRecordings( + [FromQuery] string? channelId, + [FromQuery] Guid? userId, + [FromQuery] int? startIndex, + [FromQuery] int? limit, + [FromQuery] RecordingStatus? status, + [FromQuery] bool? isInProgress, + [FromQuery] string? seriesTimerId, + [FromQuery] bool? enableImages, + [FromQuery] int? imageTypeLimit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, + [FromQuery] bool? enableUserData, + [FromQuery] bool? isMovie, + [FromQuery] bool? isSeries, + [FromQuery] bool? isKids, + [FromQuery] bool? isSports, + [FromQuery] bool? isNews, + [FromQuery] bool? isLibraryItem, + [FromQuery] bool enableTotalRecordCount = true) + { + var dtoOptions = new DtoOptions { Fields = fields } + .AddClientFields(User) + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - /// - /// Gets live tv recording groups. - /// - /// Optional. Filter by user and attach user data. - /// Recording groups returned. - /// An containing the recording groups. - [HttpGet("Recordings/Groups")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - [Obsolete("This endpoint is obsolete.")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] - public ActionResult> GetRecordingGroups([FromQuery] Guid? userId) - { - return new QueryResult(); - } + return _liveTvManager.GetRecordings( + new RecordingQuery + { + ChannelId = channelId, + UserId = userId ?? Guid.Empty, + StartIndex = startIndex, + Limit = limit, + Status = status, + SeriesTimerId = seriesTimerId, + IsInProgress = isInProgress, + EnableTotalRecordCount = enableTotalRecordCount, + IsMovie = isMovie, + IsNews = isNews, + IsSeries = isSeries, + IsKids = isKids, + IsSports = isSports, + IsLibraryItem = isLibraryItem, + Fields = fields, + ImageTypeLimit = imageTypeLimit, + EnableImages = enableImages + }, + dtoOptions); + } - /// - /// Gets recording folders. - /// - /// Optional. Filter by user and attach user data. - /// Recording folders returned. - /// An containing the recording folders. - [HttpGet("Recordings/Folders")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult> GetRecordingFolders([FromQuery] Guid? userId) - { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); - var folders = _liveTvManager.GetRecordingFolders(user); + /// + /// Gets live tv recording series. + /// + /// Optional. Filter by channel id. + /// Optional. Filter by user and attach user data. + /// Optional. Filter by recording group. + /// Optional. The record index to start at. All items with a lower index will be dropped from the results. + /// Optional. The maximum number of records to return. + /// Optional. Filter by recording status. + /// Optional. Filter by recordings that are in progress, or not. + /// Optional. Filter by recordings belonging to a series timer. + /// Optional. Include image information in output. + /// Optional. The max number of images to return, per image type. + /// Optional. The image types to include in the output. + /// Optional. Specify additional fields of information to return in the output. + /// Optional. Include user data. + /// Optional. Return total record count. + /// Live tv recordings returned. + /// An containing the live tv recordings. + [HttpGet("Recordings/Series")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + [Obsolete("This endpoint is obsolete.")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "channelId", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "groupId", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "startIndex", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "limit", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "status", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isInProgress", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "seriesTimerId", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableImages", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageTypeLimit", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableImageTypes", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "fields", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableUserData", Justification = "Imported from ServiceStack")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "enableTotalRecordCount", Justification = "Imported from ServiceStack")] + public ActionResult> GetRecordingsSeries( + [FromQuery] string? channelId, + [FromQuery] Guid? userId, + [FromQuery] string? groupId, + [FromQuery] int? startIndex, + [FromQuery] int? limit, + [FromQuery] RecordingStatus? status, + [FromQuery] bool? isInProgress, + [FromQuery] string? seriesTimerId, + [FromQuery] bool? enableImages, + [FromQuery] int? imageTypeLimit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, + [FromQuery] bool? enableUserData, + [FromQuery] bool enableTotalRecordCount = true) + { + return new QueryResult(); + } - var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user); + /// + /// Gets live tv recording groups. + /// + /// Optional. Filter by user and attach user data. + /// Recording groups returned. + /// An containing the recording groups. + [HttpGet("Recordings/Groups")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + [Obsolete("This endpoint is obsolete.")] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] + public ActionResult> GetRecordingGroups([FromQuery] Guid? userId) + { + return new QueryResult(); + } - return new QueryResult(returnArray); - } + /// + /// Gets recording folders. + /// + /// Optional. Filter by user and attach user data. + /// Recording folders returned. + /// An containing the recording folders. + [HttpGet("Recordings/Folders")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult> GetRecordingFolders([FromQuery] Guid? userId) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); + var folders = _liveTvManager.GetRecordingFolders(user); - /// - /// Gets a live tv recording. - /// - /// Recording id. - /// Optional. Attach user data. - /// Recording returned. - /// An containing the live tv recording. - [HttpGet("Recordings/{recordingId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetRecording([FromRoute, Required] Guid recordingId, [FromQuery] Guid? userId) - { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); - var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId); + var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user); - var dtoOptions = new DtoOptions() - .AddClientFields(User); + return new QueryResult(returnArray); + } - return _dtoService.GetBaseItemDto(item, dtoOptions, user); - } + /// + /// Gets a live tv recording. + /// + /// Recording id. + /// Optional. Attach user data. + /// Recording returned. + /// An containing the live tv recording. + [HttpGet("Recordings/{recordingId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public ActionResult GetRecording([FromRoute, Required] Guid recordingId, [FromQuery] Guid? userId) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); + var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId); - /// - /// Resets a tv tuner. - /// - /// Tuner id. - /// Tuner reset. - /// A . - [HttpPost("Tuners/{tunerId}/Reset")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task ResetTuner([FromRoute, Required] string tunerId) - { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.ResetTuner(tunerId, CancellationToken.None).ConfigureAwait(false); - return NoContent(); - } + var dtoOptions = new DtoOptions() + .AddClientFields(User); - /// - /// Gets a timer. - /// - /// Timer id. - /// Timer returned. - /// - /// A containing an which contains the timer. - /// - [HttpGet("Timers/{timerId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task> GetTimer([FromRoute, Required] string timerId) - { - return await _liveTvManager.GetTimer(timerId, CancellationToken.None).ConfigureAwait(false); - } + return _dtoService.GetBaseItemDto(item, dtoOptions, user); + } - /// - /// Gets the default values for a new timer. - /// - /// Optional. To attach default values based on a program. - /// Default values returned. - /// - /// A containing an which contains the default values for a timer. - /// - [HttpGet("Timers/Defaults")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task> GetDefaultTimer([FromQuery] string? programId) - { - return string.IsNullOrEmpty(programId) - ? await _liveTvManager.GetNewTimerDefaults(CancellationToken.None).ConfigureAwait(false) - : await _liveTvManager.GetNewTimerDefaults(programId, CancellationToken.None).ConfigureAwait(false); - } + /// + /// Resets a tv tuner. + /// + /// Tuner id. + /// Tuner reset. + /// A . + [HttpPost("Tuners/{tunerId}/Reset")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task ResetTuner([FromRoute, Required] string tunerId) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.ResetTuner(tunerId, CancellationToken.None).ConfigureAwait(false); + return NoContent(); + } - /// - /// Gets the live tv timers. - /// - /// Optional. Filter by channel id. - /// Optional. Filter by timers belonging to a series timer. - /// Optional. Filter by timers that are active. - /// Optional. Filter by timers that are scheduled. - /// - /// A containing an which contains the live tv timers. - /// - [HttpGet("Timers")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task>> GetTimers( - [FromQuery] string? channelId, - [FromQuery] string? seriesTimerId, - [FromQuery] bool? isActive, - [FromQuery] bool? isScheduled) - { - return await _liveTvManager.GetTimers( - new TimerQuery - { - ChannelId = channelId, - SeriesTimerId = seriesTimerId, - IsActive = isActive, - IsScheduled = isScheduled - }, - CancellationToken.None).ConfigureAwait(false); - } + /// + /// Gets a timer. + /// + /// Timer id. + /// Timer returned. + /// + /// A containing an which contains the timer. + /// + [HttpGet("Timers/{timerId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task> GetTimer([FromRoute, Required] string timerId) + { + return await _liveTvManager.GetTimer(timerId, CancellationToken.None).ConfigureAwait(false); + } - /// - /// Gets available live tv epgs. - /// - /// The channels to return guide information for. - /// Optional. Filter by user id. - /// Optional. The minimum premiere start date. - /// Optional. Filter by programs that have completed airing, or not. - /// Optional. Filter by programs that are currently airing, or not. - /// Optional. The maximum premiere start date. - /// Optional. The minimum premiere end date. - /// Optional. The maximum premiere end date. - /// Optional. Filter for movies. - /// Optional. Filter for series. - /// Optional. Filter for news. - /// Optional. Filter for kids. - /// Optional. Filter for sports. - /// Optional. The record index to start at. All items with a lower index will be dropped from the results. - /// Optional. The maximum number of records to return. - /// Optional. Specify one or more sort orders, comma delimited. Options: Name, StartDate. - /// Sort Order - Ascending,Descending. - /// The genres to return guide information for. - /// The genre ids to return guide information for. - /// Optional. Include image information in output. - /// Optional. The max number of images to return, per image type. - /// Optional. The image types to include in the output. - /// Optional. Include user data. - /// Optional. Filter by series timer id. - /// Optional. Filter by library series id. - /// Optional. Specify additional fields of information to return in the output. - /// Retrieve total record count. - /// Live tv epgs returned. - /// - /// A containing a which contains the live tv epgs. - /// - [HttpGet("Programs")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task>> GetLiveTvPrograms( - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] channelIds, - [FromQuery] Guid? userId, - [FromQuery] DateTime? minStartDate, - [FromQuery] bool? hasAired, - [FromQuery] bool? isAiring, - [FromQuery] DateTime? maxStartDate, - [FromQuery] DateTime? minEndDate, - [FromQuery] DateTime? maxEndDate, - [FromQuery] bool? isMovie, - [FromQuery] bool? isSeries, - [FromQuery] bool? isNews, - [FromQuery] bool? isKids, - [FromQuery] bool? isSports, - [FromQuery] int? startIndex, - [FromQuery] int? limit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, - [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds, - [FromQuery] bool? enableImages, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery] bool? enableUserData, - [FromQuery] string? seriesTimerId, - [FromQuery] Guid? librarySeriesId, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool enableTotalRecordCount = true) - { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); + /// + /// Gets the default values for a new timer. + /// + /// Optional. To attach default values based on a program. + /// Default values returned. + /// + /// A containing an which contains the default values for a timer. + /// + [HttpGet("Timers/Defaults")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task> GetDefaultTimer([FromQuery] string? programId) + { + return string.IsNullOrEmpty(programId) + ? await _liveTvManager.GetNewTimerDefaults(CancellationToken.None).ConfigureAwait(false) + : await _liveTvManager.GetNewTimerDefaults(programId, CancellationToken.None).ConfigureAwait(false); + } - var query = new InternalItemsQuery(user) + /// + /// Gets the live tv timers. + /// + /// Optional. Filter by channel id. + /// Optional. Filter by timers belonging to a series timer. + /// Optional. Filter by timers that are active. + /// Optional. Filter by timers that are scheduled. + /// + /// A containing an which contains the live tv timers. + /// + [HttpGet("Timers")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task>> GetTimers( + [FromQuery] string? channelId, + [FromQuery] string? seriesTimerId, + [FromQuery] bool? isActive, + [FromQuery] bool? isScheduled) + { + return await _liveTvManager.GetTimers( + new TimerQuery { - ChannelIds = channelIds, - HasAired = hasAired, - IsAiring = isAiring, - EnableTotalRecordCount = enableTotalRecordCount, - MinStartDate = minStartDate, - MinEndDate = minEndDate, - MaxStartDate = maxStartDate, - MaxEndDate = maxEndDate, - StartIndex = startIndex, - Limit = limit, - OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder), - IsNews = isNews, - IsMovie = isMovie, - IsSeries = isSeries, - IsKids = isKids, - IsSports = isSports, + ChannelId = channelId, SeriesTimerId = seriesTimerId, - Genres = genres, - GenreIds = genreIds - }; - - if (librarySeriesId.HasValue && !librarySeriesId.Equals(default)) - { - query.IsSeries = true; - - if (_libraryManager.GetItemById(librarySeriesId.Value) is Series series) - { - query.Name = series.Name; - } - } + IsActive = isActive, + IsScheduled = isScheduled + }, + CancellationToken.None).ConfigureAwait(false); + } - var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(User) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); - } + /// + /// Gets available live tv epgs. + /// + /// The channels to return guide information for. + /// Optional. Filter by user id. + /// Optional. The minimum premiere start date. + /// Optional. Filter by programs that have completed airing, or not. + /// Optional. Filter by programs that are currently airing, or not. + /// Optional. The maximum premiere start date. + /// Optional. The minimum premiere end date. + /// Optional. The maximum premiere end date. + /// Optional. Filter for movies. + /// Optional. Filter for series. + /// Optional. Filter for news. + /// Optional. Filter for kids. + /// Optional. Filter for sports. + /// Optional. The record index to start at. All items with a lower index will be dropped from the results. + /// Optional. The maximum number of records to return. + /// Optional. Specify one or more sort orders, comma delimited. Options: Name, StartDate. + /// Sort Order - Ascending,Descending. + /// The genres to return guide information for. + /// The genre ids to return guide information for. + /// Optional. Include image information in output. + /// Optional. The max number of images to return, per image type. + /// Optional. The image types to include in the output. + /// Optional. Include user data. + /// Optional. Filter by series timer id. + /// Optional. Filter by library series id. + /// Optional. Specify additional fields of information to return in the output. + /// Retrieve total record count. + /// Live tv epgs returned. + /// + /// A containing a which contains the live tv epgs. + /// + [HttpGet("Programs")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task>> GetLiveTvPrograms( + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] channelIds, + [FromQuery] Guid? userId, + [FromQuery] DateTime? minStartDate, + [FromQuery] bool? hasAired, + [FromQuery] bool? isAiring, + [FromQuery] DateTime? maxStartDate, + [FromQuery] DateTime? minEndDate, + [FromQuery] DateTime? maxEndDate, + [FromQuery] bool? isMovie, + [FromQuery] bool? isSeries, + [FromQuery] bool? isNews, + [FromQuery] bool? isKids, + [FromQuery] bool? isSports, + [FromQuery] int? startIndex, + [FromQuery] int? limit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, + [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds, + [FromQuery] bool? enableImages, + [FromQuery] int? imageTypeLimit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, + [FromQuery] bool? enableUserData, + [FromQuery] string? seriesTimerId, + [FromQuery] Guid? librarySeriesId, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, + [FromQuery] bool enableTotalRecordCount = true) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); - /// - /// Gets available live tv epgs. - /// - /// Request body. - /// Live tv epgs returned. - /// - /// A containing a which contains the live tv epgs. - /// - [HttpPost("Programs")] - [ProducesResponseType(StatusCodes.Status200OK)] - [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task>> GetPrograms([FromBody] GetProgramsDto body) + var query = new InternalItemsQuery(user) { - var user = body.UserId.Equals(default) ? null : _userManager.GetUserById(body.UserId); + ChannelIds = channelIds, + HasAired = hasAired, + IsAiring = isAiring, + EnableTotalRecordCount = enableTotalRecordCount, + MinStartDate = minStartDate, + MinEndDate = minEndDate, + MaxStartDate = maxStartDate, + MaxEndDate = maxEndDate, + StartIndex = startIndex, + Limit = limit, + OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder), + IsNews = isNews, + IsMovie = isMovie, + IsSeries = isSeries, + IsKids = isKids, + IsSports = isSports, + SeriesTimerId = seriesTimerId, + Genres = genres, + GenreIds = genreIds + }; + + if (librarySeriesId.HasValue && !librarySeriesId.Equals(default)) + { + query.IsSeries = true; - var query = new InternalItemsQuery(user) - { - ChannelIds = body.ChannelIds, - HasAired = body.HasAired, - IsAiring = body.IsAiring, - EnableTotalRecordCount = body.EnableTotalRecordCount, - MinStartDate = body.MinStartDate, - MinEndDate = body.MinEndDate, - MaxStartDate = body.MaxStartDate, - MaxEndDate = body.MaxEndDate, - StartIndex = body.StartIndex, - Limit = body.Limit, - OrderBy = RequestHelpers.GetOrderBy(body.SortBy, body.SortOrder), - IsNews = body.IsNews, - IsMovie = body.IsMovie, - IsSeries = body.IsSeries, - IsKids = body.IsKids, - IsSports = body.IsSports, - SeriesTimerId = body.SeriesTimerId, - Genres = body.Genres, - GenreIds = body.GenreIds - }; - - if (!body.LibrarySeriesId.Equals(default)) + if (_libraryManager.GetItemById(librarySeriesId.Value) is Series series) { - query.IsSeries = true; - - if (_libraryManager.GetItemById(body.LibrarySeriesId) is Series series) - { - query.Name = series.Name; - } + query.Name = series.Name; } - - var dtoOptions = new DtoOptions { Fields = body.Fields } - .AddClientFields(User) - .AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes); - return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } - /// - /// Gets recommended live tv epgs. - /// - /// Optional. filter by user id. - /// Optional. The maximum number of records to return. - /// Optional. Filter by programs that are currently airing, or not. - /// Optional. Filter by programs that have completed airing, or not. - /// Optional. Filter for series. - /// Optional. Filter for movies. - /// Optional. Filter for news. - /// Optional. Filter for kids. - /// Optional. Filter for sports. - /// Optional. Include image information in output. - /// Optional. The max number of images to return, per image type. - /// Optional. The image types to include in the output. - /// The genres to return guide information for. - /// Optional. Specify additional fields of information to return in the output. - /// Optional. include user data. - /// Retrieve total record count. - /// Recommended epgs returned. - /// A containing the queryresult of recommended epgs. - [HttpGet("Programs/Recommended")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetRecommendedPrograms( - [FromQuery] Guid? userId, - [FromQuery] int? limit, - [FromQuery] bool? isAiring, - [FromQuery] bool? hasAired, - [FromQuery] bool? isSeries, - [FromQuery] bool? isMovie, - [FromQuery] bool? isNews, - [FromQuery] bool? isKids, - [FromQuery] bool? isSports, - [FromQuery] bool? enableImages, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool? enableUserData, - [FromQuery] bool enableTotalRecordCount = true) + var dtoOptions = new DtoOptions { Fields = fields } + .AddClientFields(User) + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); + return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Gets available live tv epgs. + /// + /// Request body. + /// Live tv epgs returned. + /// + /// A containing a which contains the live tv epgs. + /// + [HttpPost("Programs")] + [ProducesResponseType(StatusCodes.Status200OK)] + [Authorize(Policy = Policies.DefaultAuthorization)] + public async Task>> GetPrograms([FromBody] GetProgramsDto body) + { + var user = body.UserId.Equals(default) ? null : _userManager.GetUserById(body.UserId); + + var query = new InternalItemsQuery(user) + { + ChannelIds = body.ChannelIds, + HasAired = body.HasAired, + IsAiring = body.IsAiring, + EnableTotalRecordCount = body.EnableTotalRecordCount, + MinStartDate = body.MinStartDate, + MinEndDate = body.MinEndDate, + MaxStartDate = body.MaxStartDate, + MaxEndDate = body.MaxEndDate, + StartIndex = body.StartIndex, + Limit = body.Limit, + OrderBy = RequestHelpers.GetOrderBy(body.SortBy, body.SortOrder), + IsNews = body.IsNews, + IsMovie = body.IsMovie, + IsSeries = body.IsSeries, + IsKids = body.IsKids, + IsSports = body.IsSports, + SeriesTimerId = body.SeriesTimerId, + Genres = body.Genres, + GenreIds = body.GenreIds + }; + + if (!body.LibrarySeriesId.Equals(default)) { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); + query.IsSeries = true; - var query = new InternalItemsQuery(user) + if (_libraryManager.GetItemById(body.LibrarySeriesId) is Series series) { - IsAiring = isAiring, - Limit = limit, - HasAired = hasAired, - IsSeries = isSeries, - IsMovie = isMovie, - IsKids = isKids, - IsNews = isNews, - IsSports = isSports, - EnableTotalRecordCount = enableTotalRecordCount, - GenreIds = genreIds - }; - - var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(User) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); - return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); + query.Name = series.Name; + } } - /// - /// Gets a live tv program. - /// - /// Program id. - /// Optional. Attach user data. - /// Program returned. - /// An containing the livetv program. - [HttpGet("Programs/{programId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetProgram( - [FromRoute, Required] string programId, - [FromQuery] Guid? userId) - { - var user = userId is null || userId.Value.Equals(default) - ? null - : _userManager.GetUserById(userId.Value); + var dtoOptions = new DtoOptions { Fields = body.Fields } + .AddClientFields(User) + .AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes); + return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); + } - return await _liveTvManager.GetProgram(programId, CancellationToken.None, user).ConfigureAwait(false); - } + /// + /// Gets recommended live tv epgs. + /// + /// Optional. filter by user id. + /// Optional. The maximum number of records to return. + /// Optional. Filter by programs that are currently airing, or not. + /// Optional. Filter by programs that have completed airing, or not. + /// Optional. Filter for series. + /// Optional. Filter for movies. + /// Optional. Filter for news. + /// Optional. Filter for kids. + /// Optional. Filter for sports. + /// Optional. Include image information in output. + /// Optional. The max number of images to return, per image type. + /// Optional. The image types to include in the output. + /// The genres to return guide information for. + /// Optional. Specify additional fields of information to return in the output. + /// Optional. include user data. + /// Retrieve total record count. + /// Recommended epgs returned. + /// A containing the queryresult of recommended epgs. + [HttpGet("Programs/Recommended")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetRecommendedPrograms( + [FromQuery] Guid? userId, + [FromQuery] int? limit, + [FromQuery] bool? isAiring, + [FromQuery] bool? hasAired, + [FromQuery] bool? isSeries, + [FromQuery] bool? isMovie, + [FromQuery] bool? isNews, + [FromQuery] bool? isKids, + [FromQuery] bool? isSports, + [FromQuery] bool? enableImages, + [FromQuery] int? imageTypeLimit, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, + [FromQuery] bool? enableUserData, + [FromQuery] bool enableTotalRecordCount = true) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); - /// - /// Deletes a live tv recording. - /// - /// Recording id. - /// Recording deleted. - /// Item not found. - /// A on success, or a if item not found. - [HttpDelete("Recordings/{recordingId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task DeleteRecording([FromRoute, Required] Guid recordingId) + var query = new InternalItemsQuery(user) { - await AssertUserCanManageLiveTv().ConfigureAwait(false); + IsAiring = isAiring, + Limit = limit, + HasAired = hasAired, + IsSeries = isSeries, + IsMovie = isMovie, + IsKids = isKids, + IsNews = isNews, + IsSports = isSports, + EnableTotalRecordCount = enableTotalRecordCount, + GenreIds = genreIds + }; + + var dtoOptions = new DtoOptions { Fields = fields } + .AddClientFields(User) + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); + return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); + } - var item = _libraryManager.GetItemById(recordingId); - if (item is null) - { - return NotFound(); - } + /// + /// Gets a live tv program. + /// + /// Program id. + /// Optional. Attach user data. + /// Program returned. + /// An containing the livetv program. + [HttpGet("Programs/{programId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetProgram( + [FromRoute, Required] string programId, + [FromQuery] Guid? userId) + { + var user = userId is null || userId.Value.Equals(default) + ? null + : _userManager.GetUserById(userId.Value); - _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = false - }); + return await _liveTvManager.GetProgram(programId, CancellationToken.None, user).ConfigureAwait(false); + } - return NoContent(); - } + /// + /// Deletes a live tv recording. + /// + /// Recording id. + /// Recording deleted. + /// Item not found. + /// A on success, or a if item not found. + [HttpDelete("Recordings/{recordingId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task DeleteRecording([FromRoute, Required] Guid recordingId) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); - /// - /// Cancels a live tv timer. - /// - /// Timer id. - /// Timer deleted. - /// A . - [HttpDelete("Timers/{timerId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelTimer([FromRoute, Required] string timerId) + var item = _libraryManager.GetItemById(recordingId); + if (item is null) { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false); - return NoContent(); + return NotFound(); } - /// - /// Updates a live tv timer. - /// - /// Timer id. - /// New timer info. - /// Timer updated. - /// A . - [HttpPost("Timers/{timerId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo) + _libraryManager.DeleteItem(item, new DeleteOptions { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); - return NoContent(); - } + DeleteFileLocation = false + }); - /// - /// Creates a live tv timer. - /// - /// New timer info. - /// Timer created. - /// A . - [HttpPost("Timers")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CreateTimer([FromBody] TimerInfoDto timerInfo) - { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.CreateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); - return NoContent(); - } + return NoContent(); + } - /// - /// Gets a live tv series timer. - /// - /// Timer id. - /// Series timer returned. - /// Series timer not found. - /// A on success, or a if timer not found. - [HttpGet("SeriesTimers/{timerId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> GetSeriesTimer([FromRoute, Required] string timerId) - { - var timer = await _liveTvManager.GetSeriesTimer(timerId, CancellationToken.None).ConfigureAwait(false); - if (timer is null) - { - return NotFound(); - } + /// + /// Cancels a live tv timer. + /// + /// Timer id. + /// Timer deleted. + /// A . + [HttpDelete("Timers/{timerId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task CancelTimer([FromRoute, Required] string timerId) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false); + return NoContent(); + } - return timer; - } + /// + /// Updates a live tv timer. + /// + /// Timer id. + /// New timer info. + /// Timer updated. + /// A . + [HttpPost("Timers/{timerId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] + public async Task UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); + return NoContent(); + } - /// - /// Gets live tv series timers. - /// - /// Optional. Sort by SortName or Priority. - /// Optional. Sort in Ascending or Descending order. - /// Timers returned. - /// An of live tv series timers. - [HttpGet("SeriesTimers")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetSeriesTimers([FromQuery] string? sortBy, [FromQuery] SortOrder? sortOrder) - { - return await _liveTvManager.GetSeriesTimers( - new SeriesTimerQuery - { - SortOrder = sortOrder ?? SortOrder.Ascending, - SortBy = sortBy - }, - CancellationToken.None).ConfigureAwait(false); - } + /// + /// Creates a live tv timer. + /// + /// New timer info. + /// Timer created. + /// A . + [HttpPost("Timers")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task CreateTimer([FromBody] TimerInfoDto timerInfo) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.CreateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); + return NoContent(); + } - /// - /// Cancels a live tv series timer. - /// - /// Timer id. - /// Timer cancelled. - /// A . - [HttpDelete("SeriesTimers/{timerId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelSeriesTimer([FromRoute, Required] string timerId) + /// + /// Gets a live tv series timer. + /// + /// Timer id. + /// Series timer returned. + /// Series timer not found. + /// A on success, or a if timer not found. + [HttpGet("SeriesTimers/{timerId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> GetSeriesTimer([FromRoute, Required] string timerId) + { + var timer = await _liveTvManager.GetSeriesTimer(timerId, CancellationToken.None).ConfigureAwait(false); + if (timer is null) { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false); - return NoContent(); + return NotFound(); } - /// - /// Updates a live tv series timer. - /// - /// Timer id. - /// New series timer info. - /// Series timer updated. - /// A . - [HttpPost("SeriesTimers/{timerId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) - { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); - return NoContent(); - } + return timer; + } - /// - /// Creates a live tv series timer. - /// - /// New series timer info. - /// Series timer info created. - /// A . - [HttpPost("SeriesTimers")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CreateSeriesTimer([FromBody] SeriesTimerInfoDto seriesTimerInfo) - { - await AssertUserCanManageLiveTv().ConfigureAwait(false); - await _liveTvManager.CreateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); - return NoContent(); - } + /// + /// Gets live tv series timers. + /// + /// Optional. Sort by SortName or Priority. + /// Optional. Sort in Ascending or Descending order. + /// Timers returned. + /// An of live tv series timers. + [HttpGet("SeriesTimers")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetSeriesTimers([FromQuery] string? sortBy, [FromQuery] SortOrder? sortOrder) + { + return await _liveTvManager.GetSeriesTimers( + new SeriesTimerQuery + { + SortOrder = sortOrder ?? SortOrder.Ascending, + SortBy = sortBy + }, + CancellationToken.None).ConfigureAwait(false); + } - /// - /// Get recording group. - /// - /// Group id. - /// A . - [HttpGet("Recordings/Groups/{groupId}")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [Obsolete("This endpoint is obsolete.")] - public ActionResult GetRecordingGroup([FromRoute, Required] Guid groupId) - { - return NotFound(); - } + /// + /// Cancels a live tv series timer. + /// + /// Timer id. + /// Timer cancelled. + /// A . + [HttpDelete("SeriesTimers/{timerId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task CancelSeriesTimer([FromRoute, Required] string timerId) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false); + return NoContent(); + } - /// - /// Get guid info. - /// - /// Guid info returned. - /// An containing the guide info. - [HttpGet("GuideInfo")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetGuideInfo() - { - return _liveTvManager.GetGuideInfo(); - } + /// + /// Updates a live tv series timer. + /// + /// Timer id. + /// New series timer info. + /// Series timer updated. + /// A . + [HttpPost("SeriesTimers/{timerId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] + public async Task UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); + return NoContent(); + } - /// - /// Adds a tuner host. - /// - /// New tuner host. - /// Created tuner host returned. - /// A containing the created tuner host. - [HttpPost("TunerHosts")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> AddTunerHost([FromBody] TunerHostInfo tunerHostInfo) - { - return await _liveTvManager.SaveTunerHost(tunerHostInfo).ConfigureAwait(false); - } + /// + /// Creates a live tv series timer. + /// + /// New series timer info. + /// Series timer info created. + /// A . + [HttpPost("SeriesTimers")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task CreateSeriesTimer([FromBody] SeriesTimerInfoDto seriesTimerInfo) + { + await AssertUserCanManageLiveTv().ConfigureAwait(false); + await _liveTvManager.CreateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); + return NoContent(); + } - /// - /// Deletes a tuner host. - /// - /// Tuner host id. - /// Tuner host deleted. - /// A . - [HttpDelete("TunerHosts")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult DeleteTunerHost([FromQuery] string? id) - { - var config = _configurationManager.GetConfiguration("livetv"); - config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray(); - _configurationManager.SaveConfiguration("livetv", config); - return NoContent(); - } + /// + /// Get recording group. + /// + /// Group id. + /// A . + [HttpGet("Recordings/Groups/{groupId}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [Obsolete("This endpoint is obsolete.")] + public ActionResult GetRecordingGroup([FromRoute, Required] Guid groupId) + { + return NotFound(); + } - /// - /// Gets default listings provider info. - /// - /// Default listings provider info returned. - /// An containing the default listings provider info. - [HttpGet("ListingProviders/Default")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetDefaultListingProvider() - { - return new ListingsProviderInfo(); - } + /// + /// Get guid info. + /// + /// Guid info returned. + /// An containing the guide info. + [HttpGet("GuideInfo")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetGuideInfo() + { + return _liveTvManager.GetGuideInfo(); + } - /// - /// Adds a listings provider. - /// - /// Password. - /// New listings info. - /// Validate listings. - /// Validate login. - /// Created listings provider returned. - /// A containing the created listings provider. - [HttpPost("ListingProviders")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - [SuppressMessage("Microsoft.Performance", "CA5350:RemoveSha1", MessageId = "AddListingProvider", Justification = "Imported from ServiceStack")] - public async Task> AddListingProvider( - [FromQuery] string? pw, - [FromBody] ListingsProviderInfo listingsProviderInfo, - [FromQuery] bool validateListings = false, - [FromQuery] bool validateLogin = false) - { - if (!string.IsNullOrEmpty(pw)) - { - // TODO: remove ToLower when Convert.ToHexString supports lowercase - // Schedules Direct requires the hex to be lowercase - listingsProviderInfo.Password = Convert.ToHexString(SHA1.HashData(Encoding.UTF8.GetBytes(pw))).ToLowerInvariant(); - } + /// + /// Adds a tuner host. + /// + /// New tuner host. + /// Created tuner host returned. + /// A containing the created tuner host. + [HttpPost("TunerHosts")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> AddTunerHost([FromBody] TunerHostInfo tunerHostInfo) + { + return await _liveTvManager.SaveTunerHost(tunerHostInfo).ConfigureAwait(false); + } - return await _liveTvManager.SaveListingProvider(listingsProviderInfo, validateLogin, validateListings).ConfigureAwait(false); - } + /// + /// Deletes a tuner host. + /// + /// Tuner host id. + /// Tuner host deleted. + /// A . + [HttpDelete("TunerHosts")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult DeleteTunerHost([FromQuery] string? id) + { + var config = _configurationManager.GetConfiguration("livetv"); + config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray(); + _configurationManager.SaveConfiguration("livetv", config); + return NoContent(); + } - /// - /// Delete listing provider. - /// - /// Listing provider id. - /// Listing provider deleted. - /// A . - [HttpDelete("ListingProviders")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult DeleteListingProvider([FromQuery] string? id) - { - _liveTvManager.DeleteListingsProvider(id); - return NoContent(); - } + /// + /// Gets default listings provider info. + /// + /// Default listings provider info returned. + /// An containing the default listings provider info. + [HttpGet("ListingProviders/Default")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetDefaultListingProvider() + { + return new ListingsProviderInfo(); + } - /// - /// Gets available lineups. - /// - /// Provider id. - /// Provider type. - /// Location. - /// Country. - /// Available lineups returned. - /// A containing the available lineups. - [HttpGet("ListingProviders/Lineups")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetLineups( - [FromQuery] string? id, - [FromQuery] string? type, - [FromQuery] string? location, - [FromQuery] string? country) + /// + /// Adds a listings provider. + /// + /// Password. + /// New listings info. + /// Validate listings. + /// Validate login. + /// Created listings provider returned. + /// A containing the created listings provider. + [HttpPost("ListingProviders")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + [SuppressMessage("Microsoft.Performance", "CA5350:RemoveSha1", MessageId = "AddListingProvider", Justification = "Imported from ServiceStack")] + public async Task> AddListingProvider( + [FromQuery] string? pw, + [FromBody] ListingsProviderInfo listingsProviderInfo, + [FromQuery] bool validateListings = false, + [FromQuery] bool validateLogin = false) + { + if (!string.IsNullOrEmpty(pw)) { - return await _liveTvManager.GetLineups(type, id, country, location).ConfigureAwait(false); + // TODO: remove ToLower when Convert.ToHexString supports lowercase + // Schedules Direct requires the hex to be lowercase + listingsProviderInfo.Password = Convert.ToHexString(SHA1.HashData(Encoding.UTF8.GetBytes(pw))).ToLowerInvariant(); } - /// - /// Gets available countries. - /// - /// Available countries returned. - /// A containing the available countries. - [HttpGet("ListingProviders/SchedulesDirect/Countries")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesFile(MediaTypeNames.Application.Json)] - public async Task GetSchedulesDirectCountries() - { - var client = _httpClientFactory.CreateClient(NamedClient.Default); - // https://json.schedulesdirect.org/20141201/available/countries - // Can't dispose the response as it's required up the call chain. - var response = await client.GetAsync(new Uri("https://json.schedulesdirect.org/20141201/available/countries")) - .ConfigureAwait(false); + return await _liveTvManager.SaveListingProvider(listingsProviderInfo, validateLogin, validateListings).ConfigureAwait(false); + } - return File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), MediaTypeNames.Application.Json); - } + /// + /// Delete listing provider. + /// + /// Listing provider id. + /// Listing provider deleted. + /// A . + [HttpDelete("ListingProviders")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult DeleteListingProvider([FromQuery] string? id) + { + _liveTvManager.DeleteListingsProvider(id); + return NoContent(); + } - /// - /// Get channel mapping options. - /// - /// Provider id. - /// Channel mapping options returned. - /// An containing the channel mapping options. - [HttpGet("ChannelMappingOptions")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetChannelMappingOptions([FromQuery] string? providerId) - { - var config = _configurationManager.GetConfiguration("livetv"); + /// + /// Gets available lineups. + /// + /// Provider id. + /// Provider type. + /// Location. + /// Country. + /// Available lineups returned. + /// A containing the available lineups. + [HttpGet("ListingProviders/Lineups")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetLineups( + [FromQuery] string? id, + [FromQuery] string? type, + [FromQuery] string? location, + [FromQuery] string? country) + { + return await _liveTvManager.GetLineups(type, id, country, location).ConfigureAwait(false); + } - var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(providerId, i.Id, StringComparison.OrdinalIgnoreCase)); + /// + /// Gets available countries. + /// + /// Available countries returned. + /// A containing the available countries. + [HttpGet("ListingProviders/SchedulesDirect/Countries")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesFile(MediaTypeNames.Application.Json)] + public async Task GetSchedulesDirectCountries() + { + var client = _httpClientFactory.CreateClient(NamedClient.Default); + // https://json.schedulesdirect.org/20141201/available/countries + // Can't dispose the response as it's required up the call chain. + var response = await client.GetAsync(new Uri("https://json.schedulesdirect.org/20141201/available/countries")) + .ConfigureAwait(false); - var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name; + return File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), MediaTypeNames.Application.Json); + } - var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(providerId, CancellationToken.None) - .ConfigureAwait(false); + /// + /// Get channel mapping options. + /// + /// Provider id. + /// Channel mapping options returned. + /// An containing the channel mapping options. + [HttpGet("ChannelMappingOptions")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetChannelMappingOptions([FromQuery] string? providerId) + { + var config = _configurationManager.GetConfiguration("livetv"); - var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(providerId, CancellationToken.None) - .ConfigureAwait(false); + var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(providerId, i.Id, StringComparison.OrdinalIgnoreCase)); - var mappings = listingsProviderInfo.ChannelMappings; + var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name; - return new ChannelMappingOptionsDto - { - 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 - }; - } + var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(providerId, CancellationToken.None) + .ConfigureAwait(false); - /// - /// Set channel mappings. - /// - /// The set channel mapping dto. - /// Created channel mapping returned. - /// An containing the created channel mapping. - [HttpPost("ChannelMappings")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> SetChannelMapping([FromBody, Required] SetChannelMappingDto setChannelMappingDto) - { - return await _liveTvManager.SetChannelMapping(setChannelMappingDto.ProviderId, setChannelMappingDto.TunerChannelId, setChannelMappingDto.ProviderChannelId).ConfigureAwait(false); - } + var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(providerId, CancellationToken.None) + .ConfigureAwait(false); - /// - /// Get tuner host types. - /// - /// Tuner host types returned. - /// An containing the tuner host types. - [HttpGet("TunerHosts/Types")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetTunerHostTypes() - { - return _liveTvManager.GetTunerHostTypes(); - } + var mappings = listingsProviderInfo.ChannelMappings; - /// - /// Discover tuners. - /// - /// Only discover new tuners. - /// Tuners returned. - /// An containing the tuners. - [HttpGet("Tuners/Discvover", Name = "DiscvoverTuners")] - [HttpGet("Tuners/Discover")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> DiscoverTuners([FromQuery] bool newDevicesOnly = false) + return new ChannelMappingOptionsDto { - return await _liveTvManager.DiscoverTuners(newDevicesOnly, CancellationToken.None).ConfigureAwait(false); - } + 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 + }; + } - /// - /// Gets a live tv recording stream. - /// - /// Recording id. - /// Recording stream returned. - /// Recording not found. - /// - /// An containing the recording stream on success, - /// or a if recording not found. - /// - [HttpGet("LiveRecordings/{recordingId}/stream")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesVideoFile] - public ActionResult GetLiveRecordingFile([FromRoute, Required] string recordingId) - { - var path = _liveTvManager.GetEmbyTvActiveRecordingPath(recordingId); + /// + /// Set channel mappings. + /// + /// The set channel mapping dto. + /// Created channel mapping returned. + /// An containing the created channel mapping. + [HttpPost("ChannelMappings")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> SetChannelMapping([FromBody, Required] SetChannelMappingDto setChannelMappingDto) + { + return await _liveTvManager.SetChannelMapping(setChannelMappingDto.ProviderId, setChannelMappingDto.TunerChannelId, setChannelMappingDto.ProviderChannelId).ConfigureAwait(false); + } - if (string.IsNullOrWhiteSpace(path)) - { - return NotFound(); - } + /// + /// Get tuner host types. + /// + /// Tuner host types returned. + /// An containing the tuner host types. + [HttpGet("TunerHosts/Types")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult> GetTunerHostTypes() + { + return _liveTvManager.GetTunerHostTypes(); + } - var stream = new ProgressiveFileStream(path, null, _transcodingJobHelper); - return new FileStreamResult(stream, MimeTypes.GetMimeType(path)); - } + /// + /// Discover tuners. + /// + /// Only discover new tuners. + /// Tuners returned. + /// An containing the tuners. + [HttpGet("Tuners/Discvover", Name = "DiscvoverTuners")] + [HttpGet("Tuners/Discover")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> DiscoverTuners([FromQuery] bool newDevicesOnly = false) + { + return await _liveTvManager.DiscoverTuners(newDevicesOnly, CancellationToken.None).ConfigureAwait(false); + } - /// - /// Gets a live tv channel stream. - /// - /// Stream id. - /// Container type. - /// Stream returned. - /// Stream not found. - /// - /// An containing the channel stream on success, - /// or a if stream not found. - /// - [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesVideoFile] - public ActionResult GetLiveStreamFile([FromRoute, Required] string streamId, [FromRoute, Required] string container) + /// + /// Gets a live tv recording stream. + /// + /// Recording id. + /// Recording stream returned. + /// Recording not found. + /// + /// An containing the recording stream on success, + /// or a if recording not found. + /// + [HttpGet("LiveRecordings/{recordingId}/stream")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesVideoFile] + public ActionResult GetLiveRecordingFile([FromRoute, Required] string recordingId) + { + var path = _liveTvManager.GetEmbyTvActiveRecordingPath(recordingId); + + if (string.IsNullOrWhiteSpace(path)) { - var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfoByUniqueId(streamId); - if (liveStreamInfo is null) - { - return NotFound(); - } + return NotFound(); + } + + var stream = new ProgressiveFileStream(path, null, _transcodingJobHelper); + return new FileStreamResult(stream, MimeTypes.GetMimeType(path)); + } - var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); - return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file." + container)); + /// + /// Gets a live tv channel stream. + /// + /// Stream id. + /// Container type. + /// Stream returned. + /// Stream not found. + /// + /// An containing the channel stream on success, + /// or a if stream not found. + /// + [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesVideoFile] + public ActionResult GetLiveStreamFile([FromRoute, Required] string streamId, [FromRoute, Required] string container) + { + var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfoByUniqueId(streamId); + if (liveStreamInfo is null) + { + return NotFound(); } - private async Task AssertUserCanManageLiveTv() + var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); + return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file." + container)); + } + + private async Task AssertUserCanManageLiveTv() + { + var user = _userManager.GetUserById(User.GetUserId()); + var session = await _sessionManager.LogSessionActivity( + User.GetClient(), + User.GetVersion(), + User.GetDeviceId(), + User.GetDevice(), + HttpContext.GetNormalizedRemoteIp().ToString(), + user).ConfigureAwait(false); + + if (session.UserId.Equals(default)) { - var user = _userManager.GetUserById(User.GetUserId()); - var session = await _sessionManager.LogSessionActivity( - User.GetClient(), - User.GetVersion(), - User.GetDeviceId(), - User.GetDevice(), - HttpContext.GetNormalizedRemoteIp().ToString(), - user).ConfigureAwait(false); - - if (session.UserId.Equals(default)) - { - throw new SecurityException("Anonymous live tv management is not allowed."); - } + 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."); - } + if (!user.HasPermission(PermissionKind.EnableLiveTvManagement)) + { + throw new SecurityException("The current user does not have permission to manage live tv."); } } } -- cgit v1.2.3