#nullable enable using System; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers { /// /// Attachments controller. /// [Route("Videos")] [Authorize] public class AttachmentsController : Controller { private readonly ILibraryManager _libraryManager; private readonly IAttachmentExtractor _attachmentExtractor; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. public AttachmentsController( ILibraryManager libraryManager, IAttachmentExtractor attachmentExtractor) { _libraryManager = libraryManager; _attachmentExtractor = attachmentExtractor; } /// /// Get video attachment. /// /// Video ID. /// Media Source ID. /// Attachment Index. /// Attachment. [HttpGet("{VideoID}/{MediaSourceID}/Attachments/{Index}")] [Produces("application/octet-stream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> GetAttachment( [FromRoute] Guid videoId, [FromRoute] string mediaSourceId, [FromRoute] 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 = "application/octet-stream"; if (string.IsNullOrWhiteSpace(attachment.MimeType)) { contentType = attachment.MimeType; } return new FileStreamResult(stream, contentType); } catch (ResourceNotFoundException e) { return StatusCode(StatusCodes.Status404NotFound, e.Message); } } } }