| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 | using System;using System.ComponentModel.DataAnnotations;using System.Net.Mime;using System.Threading;using System.Threading.Tasks;using Jellyfin.Api.Attributes;using MediaBrowser.Common.Extensions;using MediaBrowser.Controller.Library;using MediaBrowser.Controller.MediaEncoding;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;namespace Jellyfin.Api.Controllers{    /// <summary>    /// Attachments controller.    /// </summary>    [Route("Videos")]    public class VideoAttachmentsController : BaseJellyfinApiController    {        private readonly ILibraryManager _libraryManager;        private readonly IAttachmentExtractor _attachmentExtractor;        /// <summary>        /// Initializes a new instance of the <see cref="VideoAttachmentsController"/> class.        /// </summary>        /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>        /// <param name="attachmentExtractor">Instance of the <see cref="IAttachmentExtractor"/> interface.</param>        public VideoAttachmentsController(            ILibraryManager libraryManager,            IAttachmentExtractor attachmentExtractor)        {            _libraryManager = libraryManager;            _attachmentExtractor = attachmentExtractor;        }        /// <summary>        /// Get video attachment.        /// </summary>        /// <param name="videoId">Video ID.</param>        /// <param name="mediaSourceId">Media Source ID.</param>        /// <param name="index">Attachment Index.</param>        /// <response code="200">Attachment retrieved.</response>        /// <response code="404">Video or attachment not found.</response>        /// <returns>An <see cref="FileStreamResult"/> containing the attachment stream on success, or a <see cref="NotFoundResult"/> if the attachment could not be found.</returns>        [HttpGet("{videoId}/{mediaSourceId}/Attachments/{index}")]        [ProducesFile(MediaTypeNames.Application.Octet)]        [ProducesResponseType(StatusCodes.Status200OK)]        [ProducesResponseType(StatusCodes.Status404NotFound)]        public async Task<ActionResult> GetAttachment(            [FromRoute, Required] Guid videoId,            [FromRoute, Required] string mediaSourceId,            [FromRoute, Required] int index)        {            try            {                var item = _libraryManager.GetItemById(videoId);                if (item == null)                {                    return NotFound();                }                var (attachment, stream) = await _attachmentExtractor.GetAttachment(                        item,                        mediaSourceId,                        index,                        CancellationToken.None)                    .ConfigureAwait(false);                var contentType = string.IsNullOrWhiteSpace(attachment.MimeType)                    ? MediaTypeNames.Application.Octet                    : attachment.MimeType;                return new FileStreamResult(stream, contentType);            }            catch (ResourceNotFoundException e)            {                return NotFound(e.Message);            }        }    }}
 |