You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.7 KiB
170 lines
6.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Threading.Tasks;
|
|
using Jellyfin.Api.Extensions;
|
|
using Jellyfin.Api.Models.MediaSegmentsDtos;
|
|
using Jellyfin.Data.Enums.MediaSegmentType;
|
|
using Jellyfin.Extensions;
|
|
using MediaBrowser.Common.Api;
|
|
using MediaBrowser.Common.Extensions;
|
|
using MediaBrowser.Controller.Library;
|
|
using MediaBrowser.Model.MediaSegments;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace Jellyfin.Api.Controllers;
|
|
|
|
/// <summary>
|
|
/// Media Segments controller.
|
|
/// </summary>
|
|
[Authorize]
|
|
public class MediaSegmentsController : BaseJellyfinApiController
|
|
{
|
|
private readonly IUserManager _userManager;
|
|
private readonly IMediaSegmentsManager _mediaSegmentManager;
|
|
private readonly ILibraryManager _libraryManager;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="MediaSegmentsController"/> class.
|
|
/// </summary>
|
|
/// <param name="mediaSegmentManager">Instance of the <see cref="IMediaSegmentsManager"/> interface.</param>
|
|
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
|
/// <param name="libraryManager">The library manager.</param>
|
|
public MediaSegmentsController(
|
|
IMediaSegmentsManager mediaSegmentManager,
|
|
IUserManager userManager,
|
|
ILibraryManager libraryManager)
|
|
{
|
|
_userManager = userManager;
|
|
_mediaSegmentManager = mediaSegmentManager;
|
|
_libraryManager = libraryManager;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all media segments.
|
|
/// </summary>
|
|
/// <param name="itemId">The item id.</param>
|
|
/// <param name="streamIndex">Just segments with MediaStreamIndex.</param>
|
|
/// <param name="type">All segments of type.</param>
|
|
/// <param name="typeIndex">All segments with typeIndex.</param>
|
|
/// <response code="200">Segments returned.</response>
|
|
/// <response code="404">itemId doesn't exist.</response>
|
|
/// <response code="401">User is not authorized to access the requested item.</response>
|
|
/// <returns>An <see cref="OkResult"/>containing the found segments.</returns>
|
|
[HttpGet("{itemId}")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<ActionResult<IReadOnlyList<MediaSegmentDto>>> GetSegments(
|
|
[FromRoute, Required] Guid itemId,
|
|
[FromQuery] int? streamIndex,
|
|
[FromQuery] MediaSegmentType? type,
|
|
[FromQuery] int? typeIndex)
|
|
{
|
|
var isApiKey = User.GetIsApiKey();
|
|
var userId = User.GetUserId();
|
|
var user = !isApiKey && !userId.IsEmpty()
|
|
? _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException()
|
|
: null;
|
|
|
|
var item = _libraryManager.GetItemById(itemId);
|
|
if (item is null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
if (!isApiKey && !item.IsVisible(user))
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
var list = await _mediaSegmentManager.GetAllMediaSegments(itemId, streamIndex, typeIndex, type).ConfigureAwait(false);
|
|
return Ok(list.ConvertAll(MediaSegmentDto.FromMediaSegment));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create or update multiple media segments.
|
|
/// </summary>
|
|
/// <param name="itemId">The item the segments belong to.</param>
|
|
/// <param name="segments">All segments that should be added.</param>
|
|
/// <response code="200">Segments returned.</response>
|
|
/// <response code="400">Invalid segments.</response>
|
|
/// <response code="401">User is not authorized to access the requested item.</response>
|
|
/// <returns>An <see cref="OkResult"/>containing the created/updated segments.</returns>
|
|
[HttpPost("{itemId}")]
|
|
[Authorize(Policy = Policies.MediaSegmentsManagement)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<ActionResult<IReadOnlyList<MediaSegmentDto>>> CreateSegments(
|
|
[FromRoute, Required] Guid itemId,
|
|
[FromBody, Required] IReadOnlyList<MediaSegmentDto> segments)
|
|
{
|
|
var isApiKey = User.GetIsApiKey();
|
|
var userId = User.GetUserId();
|
|
var user = !isApiKey && !userId.IsEmpty()
|
|
? _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException()
|
|
: null;
|
|
|
|
var item = _libraryManager.GetItemById(itemId);
|
|
if (item is null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
if (!isApiKey && !item.IsVisible(user))
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
var segmentsToAdd = segments.ConvertAll(s => s.ToMediaSegment());
|
|
var addedSegments = await _mediaSegmentManager.CreateMediaSegments(itemId, segmentsToAdd).ConfigureAwait(false);
|
|
return Ok(addedSegments.ConvertAll(MediaSegmentDto.FromMediaSegment));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete media segments. All query parameters can be freely defined.
|
|
/// </summary>
|
|
/// <param name="itemId">The item id.</param>
|
|
/// <param name="streamIndex">Segment is associated with MediaStreamIndex.</param>
|
|
/// <param name="type">All segments of type.</param>
|
|
/// <param name="typeIndex">All segments with typeIndex.</param>
|
|
/// <response code="200">Segments deleted.</response>
|
|
/// <response code="404">Segments not found.</response>
|
|
/// <response code="401">User is not authorized to access the requested item.</response>
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
[HttpDelete("{itemId}")]
|
|
[Authorize(Policy = Policies.MediaSegmentsManagement)]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<IActionResult> DeleteSegments(
|
|
[FromRoute, Required] Guid itemId,
|
|
[FromQuery] int? streamIndex,
|
|
[FromQuery] MediaSegmentType? type,
|
|
[FromQuery] int? typeIndex)
|
|
{
|
|
var isApiKey = User.GetIsApiKey();
|
|
var userId = User.GetUserId();
|
|
var user = !isApiKey && !userId.IsEmpty()
|
|
? _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException()
|
|
: null;
|
|
|
|
var item = _libraryManager.GetItemById(itemId);
|
|
if (item is null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
if (!isApiKey && !item.IsVisible(user))
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
await _mediaSegmentManager.DeleteSegments(itemId, streamIndex, typeIndex, type).ConfigureAwait(false);
|
|
return Ok();
|
|
}
|
|
}
|