This commit is contained in:
Flaminel
2025-05-14 22:42:52 +03:00
parent 461e935128
commit 69788d55d2
11 changed files with 1141 additions and 7 deletions

View File

@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace Executable.Controllers;
[ApiController]
[Route("")]
public class ApiDocumentationController : ControllerBase
{
[HttpGet]
public IActionResult RedirectToSwagger()
{
return Redirect("/swagger");
}
}

View File

@@ -0,0 +1,154 @@
using Common.Configuration.ContentBlocker;
using Common.Configuration.DownloadCleaner;
using Common.Configuration.QueueCleaner;
using Infrastructure.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Text.Json;
namespace Executable.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ConfigurationController : ControllerBase
{
private readonly ILogger<ConfigurationController> _logger;
private readonly IConfiguration _configuration;
private readonly IOptionsMonitor<QueueCleanerConfig> _queueCleanerConfig;
private readonly IOptionsMonitor<ContentBlockerConfig> _contentBlockerConfig;
private readonly IOptionsMonitor<DownloadCleanerConfig> _downloadCleanerConfig;
private readonly IConfigurationService _configService;
public ConfigurationController(
ILogger<ConfigurationController> logger,
IConfiguration configuration,
IOptionsMonitor<QueueCleanerConfig> queueCleanerConfig,
IOptionsMonitor<ContentBlockerConfig> contentBlockerConfig,
IOptionsMonitor<DownloadCleanerConfig> downloadCleanerConfig,
IConfigurationService configService)
{
_logger = logger;
_configuration = configuration;
_queueCleanerConfig = queueCleanerConfig;
_contentBlockerConfig = contentBlockerConfig;
_downloadCleanerConfig = downloadCleanerConfig;
_configService = configService;
}
[HttpGet("queuecleaner")]
public IActionResult GetQueueCleanerConfig()
{
try
{
return Ok(_queueCleanerConfig.CurrentValue);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving QueueCleaner configuration");
return StatusCode(500, "An error occurred while retrieving QueueCleaner configuration");
}
}
[HttpGet("contentblocker")]
public IActionResult GetContentBlockerConfig()
{
try
{
return Ok(_contentBlockerConfig.CurrentValue);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving ContentBlocker configuration");
return StatusCode(500, "An error occurred while retrieving ContentBlocker configuration");
}
}
[HttpGet("downloadcleaner")]
public IActionResult GetDownloadCleanerConfig()
{
try
{
return Ok(_downloadCleanerConfig.CurrentValue);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving DownloadCleaner configuration");
return StatusCode(500, "An error occurred while retrieving DownloadCleaner configuration");
}
}
[HttpPut("queuecleaner")]
public async Task<IActionResult> UpdateQueueCleanerConfig([FromBody] QueueCleanerConfig config)
{
try
{
// Validate the configuration
config.Validate();
// Persist the configuration
var result = await _configService.UpdateConfigurationAsync(QueueCleanerConfig.SectionName, config);
if (!result)
{
return StatusCode(500, "Failed to save QueueCleaner configuration");
}
_logger.LogInformation("QueueCleaner configuration updated successfully");
return Ok(new { Message = "QueueCleaner configuration updated successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating QueueCleaner configuration");
return StatusCode(500, "An error occurred while updating QueueCleaner configuration");
}
}
[HttpPut("contentblocker")]
public async Task<IActionResult> UpdateContentBlockerConfig([FromBody] ContentBlockerConfig config)
{
try
{
// Validate the configuration
config.Validate();
// Persist the configuration
var result = await _configService.UpdateConfigurationAsync(ContentBlockerConfig.SectionName, config);
if (!result)
{
return StatusCode(500, "Failed to save ContentBlocker configuration");
}
_logger.LogInformation("ContentBlocker configuration updated successfully");
return Ok(new { Message = "ContentBlocker configuration updated successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating ContentBlocker configuration");
return StatusCode(500, "An error occurred while updating ContentBlocker configuration");
}
}
[HttpPut("downloadcleaner")]
public async Task<IActionResult> UpdateDownloadCleanerConfig([FromBody] DownloadCleanerConfig config)
{
try
{
// Validate the configuration
config.Validate();
// Persist the configuration
var result = await _configService.UpdateConfigurationAsync(DownloadCleanerConfig.SectionName, config);
if (!result)
{
return StatusCode(500, "Failed to save DownloadCleaner configuration");
}
_logger.LogInformation("DownloadCleaner configuration updated successfully");
return Ok(new { Message = "DownloadCleaner configuration updated successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating DownloadCleaner configuration");
return StatusCode(500, "An error occurred while updating DownloadCleaner configuration");
}
}
}

View File

@@ -0,0 +1,153 @@
using Infrastructure.Models;
using Infrastructure.Services;
using Microsoft.AspNetCore.Mvc;
namespace Executable.Controllers;
[ApiController]
[Route("api/[controller]")]
public class JobsController : ControllerBase
{
private readonly IJobManagementService _jobManagementService;
private readonly ILogger<JobsController> _logger;
public JobsController(IJobManagementService jobManagementService, ILogger<JobsController> logger)
{
_jobManagementService = jobManagementService;
_logger = logger;
}
[HttpGet]
public async Task<IActionResult> GetAllJobs()
{
try
{
var result = await _jobManagementService.GetAllJobs();
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting all jobs");
return StatusCode(500, "An error occurred while retrieving jobs");
}
}
[HttpGet("{jobName}")]
public async Task<IActionResult> GetJob(string jobName)
{
try
{
var jobInfo = await _jobManagementService.GetJob(jobName);
if (jobInfo.Status == "Not Found")
{
return NotFound($"Job '{jobName}' not found");
}
return Ok(jobInfo);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting job {jobName}", jobName);
return StatusCode(500, $"An error occurred while retrieving job '{jobName}'");
}
}
[HttpPost("{jobName}/start")]
public async Task<IActionResult> StartJob(string jobName, [FromQuery] string cronExpression = null)
{
try
{
var result = await _jobManagementService.StartJob(jobName, cronExpression);
if (!result)
{
return BadRequest($"Failed to start job '{jobName}'");
}
return Ok(new { Message = $"Job '{jobName}' started successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error starting job {jobName}", jobName);
return StatusCode(500, $"An error occurred while starting job '{jobName}'");
}
}
[HttpPost("{jobName}/stop")]
public async Task<IActionResult> StopJob(string jobName)
{
try
{
var result = await _jobManagementService.StopJob(jobName);
if (!result)
{
return BadRequest($"Failed to stop job '{jobName}'");
}
return Ok(new { Message = $"Job '{jobName}' stopped successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error stopping job {jobName}", jobName);
return StatusCode(500, $"An error occurred while stopping job '{jobName}'");
}
}
[HttpPost("{jobName}/pause")]
public async Task<IActionResult> PauseJob(string jobName)
{
try
{
var result = await _jobManagementService.PauseJob(jobName);
if (!result)
{
return BadRequest($"Failed to pause job '{jobName}'");
}
return Ok(new { Message = $"Job '{jobName}' paused successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error pausing job {jobName}", jobName);
return StatusCode(500, $"An error occurred while pausing job '{jobName}'");
}
}
[HttpPost("{jobName}/resume")]
public async Task<IActionResult> ResumeJob(string jobName)
{
try
{
var result = await _jobManagementService.ResumeJob(jobName);
if (!result)
{
return BadRequest($"Failed to resume job '{jobName}'");
}
return Ok(new { Message = $"Job '{jobName}' resumed successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error resuming job {jobName}", jobName);
return StatusCode(500, $"An error occurred while resuming job '{jobName}'");
}
}
[HttpPut("{jobName}/schedule")]
public async Task<IActionResult> UpdateJobSchedule(string jobName, [FromQuery] string cronExpression)
{
if (string.IsNullOrEmpty(cronExpression))
{
return BadRequest("Cron expression is required");
}
try
{
var result = await _jobManagementService.UpdateJobSchedule(jobName, cronExpression);
if (!result)
{
return BadRequest($"Failed to update schedule for job '{jobName}'");
}
return Ok(new { Message = $"Job '{jobName}' schedule updated successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating job {jobName} schedule", jobName);
return StatusCode(500, $"An error occurred while updating schedule for job '{jobName}'");
}
}
}

View File

@@ -0,0 +1,257 @@
using Common.Configuration.Arr;
using Common.Configuration.DownloadClient;
using Infrastructure.Verticals.Arr;
using Infrastructure.Verticals.DownloadClient;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Diagnostics;
namespace Executable.Controllers;
[ApiController]
[Route("api/[controller]")]
public class StatusController : ControllerBase
{
private readonly ILogger<StatusController> _logger;
private readonly IOptionsMonitor<DownloadClientConfig> _downloadClientConfig;
private readonly IOptionsMonitor<SonarrConfig> _sonarrConfig;
private readonly IOptionsMonitor<RadarrConfig> _radarrConfig;
private readonly IOptionsMonitor<LidarrConfig> _lidarrConfig;
private readonly DownloadServiceFactory _downloadServiceFactory;
private readonly ArrClientFactory _arrClientFactory;
public StatusController(
ILogger<StatusController> logger,
IOptionsMonitor<DownloadClientConfig> downloadClientConfig,
IOptionsMonitor<SonarrConfig> sonarrConfig,
IOptionsMonitor<RadarrConfig> radarrConfig,
IOptionsMonitor<LidarrConfig> lidarrConfig,
DownloadServiceFactory downloadServiceFactory,
ArrClientFactory arrClientFactory)
{
_logger = logger;
_downloadClientConfig = downloadClientConfig;
_sonarrConfig = sonarrConfig;
_radarrConfig = radarrConfig;
_lidarrConfig = lidarrConfig;
_downloadServiceFactory = downloadServiceFactory;
_arrClientFactory = arrClientFactory;
}
[HttpGet]
public IActionResult GetSystemStatus()
{
try
{
var process = Process.GetCurrentProcess();
var status = new
{
Application = new
{
Version = GetType().Assembly.GetName().Version?.ToString() ?? "Unknown",
StartTime = process.StartTime,
UpTime = DateTime.Now - process.StartTime,
MemoryUsageMB = Math.Round(process.WorkingSet64 / 1024.0 / 1024.0, 2),
ProcessorTime = process.TotalProcessorTime
},
DownloadClient = new
{
Type = _downloadClientConfig.CurrentValue.DownloadClient.ToString(),
IsConfigured = _downloadClientConfig.CurrentValue.DownloadClient != Common.Enums.DownloadClient.None &&
_downloadClientConfig.CurrentValue.DownloadClient != Common.Enums.DownloadClient.Disabled
},
MediaManagers = new
{
Sonarr = new
{
IsEnabled = _sonarrConfig.CurrentValue.Enabled,
InstanceCount = _sonarrConfig.CurrentValue.Instances?.Count ?? 0
},
Radarr = new
{
IsEnabled = _radarrConfig.CurrentValue.Enabled,
InstanceCount = _radarrConfig.CurrentValue.Instances?.Count ?? 0
},
Lidarr = new
{
IsEnabled = _lidarrConfig.CurrentValue.Enabled,
InstanceCount = _lidarrConfig.CurrentValue.Instances?.Count ?? 0
}
}
};
return Ok(status);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving system status");
return StatusCode(500, "An error occurred while retrieving system status");
}
}
[HttpGet("download-client")]
public async Task<IActionResult> GetDownloadClientStatus()
{
try
{
if (_downloadClientConfig.CurrentValue.DownloadClient == Common.Enums.DownloadClient.None ||
_downloadClientConfig.CurrentValue.DownloadClient == Common.Enums.DownloadClient.Disabled)
{
return NotFound("No download client is configured");
}
var downloadService = _downloadServiceFactory.CreateDownloadClient();
try
{
await downloadService.LoginAsync();
// Basic status info that should be safe for any download client
var status = new
{
IsConnected = true,
ClientType = _downloadClientConfig.CurrentValue.DownloadClient.ToString(),
Message = "Successfully connected to download client"
};
return Ok(status);
}
catch (Exception ex)
{
return StatusCode(503, new
{
IsConnected = false,
ClientType = _downloadClientConfig.CurrentValue.DownloadClient.ToString(),
Message = $"Failed to connect to download client: {ex.Message}"
});
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving download client status");
return StatusCode(500, "An error occurred while retrieving download client status");
}
}
[HttpGet("media-managers")]
public async Task<IActionResult> GetMediaManagersStatus()
{
try
{
var status = new Dictionary<string, object>();
// Check Sonarr instances
if (_sonarrConfig.CurrentValue.Enabled && _sonarrConfig.CurrentValue.Instances?.Count > 0)
{
var sonarrStatus = new List<object>();
foreach (var instance in _sonarrConfig.CurrentValue.Instances)
{
try
{
var sonarrClient = _arrClientFactory.GetClient(Domain.Enums.InstanceType.Sonarr);
await sonarrClient.TestConnectionAsync(instance);
sonarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = true,
Message = "Successfully connected"
});
}
catch (Exception ex)
{
sonarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = false,
Message = $"Connection failed: {ex.Message}"
});
}
}
status["Sonarr"] = sonarrStatus;
}
// Check Radarr instances
if (_radarrConfig.CurrentValue.Enabled && _radarrConfig.CurrentValue.Instances?.Count > 0)
{
var radarrStatus = new List<object>();
foreach (var instance in _radarrConfig.CurrentValue.Instances)
{
try
{
var radarrClient = _arrClientFactory.GetClient(Domain.Enums.InstanceType.Radarr);
await radarrClient.TestConnectionAsync(instance);
radarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = true,
Message = "Successfully connected"
});
}
catch (Exception ex)
{
radarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = false,
Message = $"Connection failed: {ex.Message}"
});
}
}
status["Radarr"] = radarrStatus;
}
// Check Lidarr instances
if (_lidarrConfig.CurrentValue.Enabled && _lidarrConfig.CurrentValue.Instances?.Count > 0)
{
var lidarrStatus = new List<object>();
foreach (var instance in _lidarrConfig.CurrentValue.Instances)
{
try
{
var lidarrClient = _arrClientFactory.GetClient(Domain.Enums.InstanceType.Lidarr);
await lidarrClient.TestConnectionAsync(instance);
lidarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = true,
Message = "Successfully connected"
});
}
catch (Exception ex)
{
lidarrStatus.Add(new
{
Name = instance.Name,
Url = instance.Url,
IsConnected = false,
Message = $"Connection failed: {ex.Message}"
});
}
}
status["Lidarr"] = lidarrStatus;
}
return Ok(status);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving media managers status");
return StatusCode(500, "An error occurred while retrieving media managers status");
}
}
}