using System; using System.Collections.Generic; using System.Linq; using Jellyfin.Data.Enums; using Jellyfin.Plugin.JRay.Models; using Jellyfin.Plugin.JRay.Services.Interfaces; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Plugin.JRay.Controllers; /// /// Lets a remote extraction worker discover which library items still need /// to be processed. /// [ApiController] [Route("Plugins/JRay/Tasks")] [Authorize(Roles = "Administrator")] public class TasksController : ControllerBase { private const int DefaultLimit = 10; private const int MaxLimit = 100; private readonly ILibraryManager _libraryManager; private readonly ITruthDataService _truthDataService; /// /// Initializes a new instance of the class. /// /// The Jellyfin library manager. /// The truth data service. public TasksController(ILibraryManager libraryManager, ITruthDataService truthDataService) { _libraryManager = libraryManager; _truthDataService = truthDataService; } /// /// Gets a random sample of movies/episodes that have no truth data yet. /// /// The maximum number of items to return (default 10, max 100). /// Up to items with no truth data, in random order. [HttpGet("Pending")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetPending([FromQuery] int limit = DefaultLimit) { var effectiveLimit = Math.Clamp(limit, 1, MaxLimit); var items = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Episode }, IsVirtualItem = false, Recursive = true, }); var pending = items .Where(item => !string.IsNullOrEmpty(item.Path) && !_truthDataService.HasTruth(item.Id, item.Path)) .OrderBy(_ => Random.Shared.Next()) .Take(effectiveLimit) .Select(item => new PendingExtractionItem { ItemId = item.Id, Path = item.Path, Name = item.Name }); return Ok(pending); } }