using System; using System.Threading; using System.Threading.Tasks; using Jellyfin.Plugin.MovieNight.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Plugin.MovieNight.Controllers; /// /// Admin endpoints for the MovieNight plugin. /// [ApiController] [Authorize] [Route("MovieNight")] public class MovieNightController : ControllerBase { private readonly MovieNightBackendClient _backendClient; private readonly MovieNightSyncService _syncService; /// /// Initializes a new instance of the class. /// public MovieNightController(MovieNightBackendClient backendClient, MovieNightSyncService syncService) { _backendClient = backendClient; _syncService = syncService; } /// /// Returns plugin status. /// /// Status response. [HttpGet("Status")] public ActionResult GetStatus() { var configuration = Plugin.Instance?.Configuration; return new MovieNightPluginStatus( Enabled: configuration?.Enabled ?? false, BackendBaseUrl: configuration?.BackendBaseUrl ?? string.Empty, PeriodicSyncEnabled: configuration?.EnablePeriodicSync ?? false, PlaybackEventsEnabled: configuration?.EnablePlaybackEvents ?? false, SyncIntervalMinutes: configuration?.SyncIntervalMinutes ?? 30); } /// /// Tests backend connectivity. /// /// Cancellation token. /// Connection result. [HttpPost("TestConnection")] public async Task> TestConnection(CancellationToken cancellationToken) { return await _backendClient.TestConnectionAsync(cancellationToken).ConfigureAwait(false); } /// /// Triggers backend sync. /// /// Cancellation token. /// Backend response. [HttpPost("Sync")] public async Task> Sync(CancellationToken cancellationToken) { await _syncService.PerformSyncAsync(cancellationToken).ConfigureAwait(false); return Ok("Sync triggered"); } /// /// Gets backend sync state. /// /// Cancellation token. /// Backend response. [HttpGet("SyncState")] public async Task> SyncState(CancellationToken cancellationToken) { return await _backendClient.GetSyncStateAsync(cancellationToken).ConfigureAwait(false); } /// /// Gets recommendations for the current user. /// [HttpGet("Users/{userId}/Recommendations")] public async Task> GetRecommendations( [FromRoute] string userId, [FromQuery] string? contentType, [FromQuery] string? mood, [FromQuery] int limit = 10, CancellationToken cancellationToken = default) { return await _backendClient.GetRecommendationsAsync(userId, contentType, mood, limit, cancellationToken).ConfigureAwait(false); } /// /// Posts a rating for a film. /// [HttpPost("Users/{userId}/Ratings/Films/{filmId}")] public async Task PostRating( [FromRoute] string userId, [FromRoute] string filmId, [FromBody] RatingRequest request, CancellationToken cancellationToken) { await _backendClient.PostRatingAsync(userId, filmId, request.Score, request.Note, cancellationToken).ConfigureAwait(false); return Ok(); } /// /// Marks a film as viewed. /// [HttpPost("Users/{userId}/Library/Films/{filmId}/Viewed")] public async Task MarkViewed( [FromRoute] string userId, [FromRoute] string filmId, [FromBody] ViewedRequest request, CancellationToken cancellationToken) { await _backendClient.MarkViewedAsync(userId, filmId, request.WatchedAt, cancellationToken).ConfigureAwait(false); return Ok(); } } /// /// Rating request. /// public sealed record RatingRequest(int Score, string? Note); /// /// Viewed request. /// public sealed record ViewedRequest(DateTimeOffset? WatchedAt); /// /// MovieNight plugin status response. /// /// Whether integration is enabled. /// Backend base URL. /// Whether periodic sync is enabled. /// Whether playback events are enabled. /// Sync interval in minutes. public sealed record MovieNightPluginStatus( bool Enabled, string BackendBaseUrl, bool PeriodicSyncEnabled, bool PlaybackEventsEnabled, int SyncIntervalMinutes);