diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs new file mode 100644 index 0000000000..532ce59c50 --- /dev/null +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -0,0 +1,202 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Threading; +using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; +using Jellyfin.Api.Helpers; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Jellyfin.Api.Controllers +{ + /// + /// The videos controller. + /// + [Route("Videos")] + public class VideosController : BaseJellyfinApiController + { + private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; + private readonly IDtoService _dtoService; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + public VideosController( + ILibraryManager libraryManager, + IUserManager userManager, + IDtoService dtoService) + { + _libraryManager = libraryManager; + _userManager = userManager; + _dtoService = dtoService; + } + + /// + /// Gets additional parts for a video. + /// + /// The item id. + /// Optional. Filter by user id, and attach user data. + /// Additional parts returned. + /// A with the parts. + [HttpGet("{itemId}/AdditionalParts")] + [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult> GetAdditionalPart([FromRoute] Guid itemId, [FromQuery] Guid userId) + { + var user = !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId) : null; + + var item = itemId.Equals(Guid.Empty) + ? (!userId.Equals(Guid.Empty) + ? _libraryManager.GetUserRootFolder() + : _libraryManager.RootFolder) + : _libraryManager.GetItemById(itemId); + + var dtoOptions = new DtoOptions(); + dtoOptions = dtoOptions.AddClientFields(Request); + + BaseItemDto[] items; + if (item is Video video) + { + items = video.GetAdditionalParts() + .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video)) + .ToArray(); + } + else + { + items = Array.Empty(); + } + + var result = new QueryResult + { + Items = items, + TotalRecordCount = items.Length + }; + + return result; + } + + /// + /// Removes alternate video sources. + /// + /// The item id. + /// Alternate sources deleted. + /// Video not found. + /// A indicating success, or a if the video doesn't exist. + [HttpDelete("{itemId}/AlternateSources")] + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public ActionResult DeleteAlternateSources([FromRoute] Guid itemId) + { + var video = (Video)_libraryManager.GetItemById(itemId); + + if (video == null) + { + return NotFound("The video either does not exist or the id does not belong to a video."); + } + + foreach (var link in video.GetLinkedAlternateVersions()) + { + link.SetPrimaryVersionId(null); + link.LinkedAlternateVersions = Array.Empty(); + + link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + } + + video.LinkedAlternateVersions = Array.Empty(); + video.SetPrimaryVersionId(null); + video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + + return NoContent(); + } + + /// + /// Merges videos into a single record. + /// + /// Item id list. This allows multiple, comma delimited. + /// Videos merged. + /// Supply at least 2 video ids. + /// A indicating success, or a if less than two ids were supplied. + [HttpPost("MergeVersions")] + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public ActionResult MergeVersions([FromQuery] string itemIds) + { + var items = RequestHelpers.Split(itemIds, ',', true) + .Select(i => _libraryManager.GetItemById(i)) + .OfType