using System; using System.Collections.Generic; using System.Net.Mime; using MediaBrowser.Controller.Entities.TV; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace ConfusedPolarBear.Plugin.IntroSkipper.Controllers; /// /// Skip intro controller. /// [Authorize] [ApiController] [Produces(MediaTypeNames.Application.Json)] public class SkipIntroController : ControllerBase { /// /// Initializes a new instance of the class. /// public SkipIntroController() { } /// /// Returns the timestamps of the introduction in a television episode. Responses are in API version 1 format. /// /// ID of the episode. Required. /// Episode contains an intro. /// Failed to find an intro in the provided episode. /// Detected intro. [HttpGet("Episode/{id}/IntroTimestamps")] [HttpGet("Episode/{id}/IntroTimestamps/v1")] public ActionResult GetIntroTimestamps([FromRoute] Guid id) { var intro = GetIntro(id); if (intro is null || !intro.Valid) { return NotFound(); } // Populate the prompt show/hide times. var config = Plugin.Instance!.Configuration; intro.ShowSkipPromptAt = Math.Max(0, intro.IntroStart - config.ShowPromptAdjustment); intro.HideSkipPromptAt = intro.IntroStart + config.HidePromptAdjustment; intro.IntroEnd -= config.SecondsOfIntroToPlay; return intro; } /// Lookup and return the intro timestamps for the provided item. /// Unique identifier of this episode. /// Intro object if the provided item has an intro, null otherwise. private Intro? GetIntro(Guid id) { return Plugin.Instance!.Intros.TryGetValue(id, out var intro) ? intro : null; } /// /// Erases all previously discovered introduction timestamps. /// /// Operation successful. /// No content. [Authorize(Policy = "RequiresElevation")] [HttpPost("Intros/EraseTimestamps")] public ActionResult ResetIntroTimestamps() { Plugin.Instance!.Intros.Clear(); Plugin.Instance!.SaveTimestamps(); return NoContent(); } /// /// Get all introductions. Only used by the end to end testing script. /// /// All introductions have been returned. /// List of IntroWithMetadata objects. [Authorize(Policy = "RequiresElevation")] [HttpGet("Intros/All")] public ActionResult> GetAllIntros() { List intros = new(); // Get metadata for all intros foreach (var intro in Plugin.Instance!.Intros) { // Get the details of the item from Jellyfin var rawItem = Plugin.Instance!.GetItem(intro.Key); if (rawItem is not Episode episode) { throw new InvalidCastException("Unable to cast item id " + intro.Key + " to an Episode"); } // Associate the metadata with the intro intros.Add( new IntroWithMetadata( episode.SeriesName, episode.AiredSeasonNumber ?? 0, episode.Name, intro.Value)); } return intros; } }