using Jellyfin.Plugin.MediaCleaner.Models; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using System.Web; using Microsoft.AspNetCore.Http; using System.Linq; namespace Jellyfin.Plugin.MediaCleaner.Controllers; public record ConnectionTestRequest(string Address, string ApiKey); public record RadarrMovie( [property: JsonPropertyName("id")] int? Id, [property: JsonPropertyName("title")] string? Title ); [Route("radarr")] public class RadarrController : Controller { private static Configuration Configuration => Plugin.Instance!.Configuration; private readonly HttpClient _httpClient; public RadarrController(HttpClient httpClient) { _httpClient = httpClient; // Set the default request headers _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); _httpClient.DefaultRequestHeaders.Add("X-Api-Key", Configuration.RadarrAPIKey); } [HttpPost("deleteMovieFromRadarr")] public async Task DeleteMovieFromRadarr([FromBody] MovieInfo movieInfo){ if (movieInfo == null || string.IsNullOrEmpty(movieInfo.TmdbId)) { return BadRequest("Invalid movie information provided."); } try { var uriBuilder = new UriBuilder($"{Configuration.RadarrAddress}/api/v3/movie"); var query = HttpUtility.ParseQueryString(uriBuilder.Query); query["tmdbId"] = movieInfo.TmdbId; query["excludeLocalCovers"] = "false"; uriBuilder.Query = query.ToString(); var response = await _httpClient.GetAsync(uriBuilder.Uri).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var movies = JsonSerializer.Deserialize>(responseBody); var movie = movies?.FirstOrDefault(); if (movie == null) { return NotFound("Movie not found in Radarr library."); } return Ok(movie); } catch (HttpRequestException e) { return StatusCode(StatusCodes.Status500InternalServerError, $"An unexpected error occurred. {e.Message}"); } } [HttpPost("testConnection")] public async Task TestConnection([FromBody] ConnectionTestRequest request) { if (request == null || string.IsNullOrWhiteSpace(request.Address) || string.IsNullOrWhiteSpace(request.ApiKey)) { return BadRequest("Address and ApiKey are required."); } var address = request.Address.Trim(); if (!address.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !address.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { address = "http://" + address; } try { using var httpRequest = new HttpRequestMessage(HttpMethod.Get, address); httpRequest.Headers.Add("X-Api-Key", request.ApiKey); var response = await _httpClient.SendAsync(httpRequest).ConfigureAwait(false); return Ok(new { success = response.IsSuccessStatusCode }); } catch (HttpRequestException e) { return StatusCode(StatusCodes.Status502BadGateway, e.Message); } catch (Exception e) { return StatusCode(StatusCodes.Status500InternalServerError, e.Message); } } }