using Common.Configuration.DownloadClient;
using Common.Enums;
using Infrastructure.Configuration;
using Infrastructure.Verticals.DownloadClient;
using Infrastructure.Verticals.DownloadClient.Factory;
using Microsoft.AspNetCore.Mvc;
namespace Executable.Controllers;
///
/// Controller for managing individual download clients
///
[ApiController]
[Route("api/clients")]
public class DownloadClientsController : ControllerBase
{
private readonly ILogger _logger;
private readonly IConfigManager _configManager;
private readonly IDownloadClientFactory _clientFactory;
///
/// Initializes a new instance of the class
///
public DownloadClientsController(
ILogger logger,
IConfigManager configManager,
IDownloadClientFactory clientFactory)
{
_logger = logger;
_configManager = configManager;
_clientFactory = clientFactory;
}
///
/// Gets all download clients
///
[HttpGet]
public async Task GetAllClients()
{
try
{
var config = await _configManager.GetConfigurationAsync();
// TODO don't expose passwords
return Ok(config.Clients);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving download clients");
return StatusCode(500, new { Error = "An error occurred while retrieving download clients" });
}
}
///
/// Gets a specific download client by ID
///
[HttpGet("{id:guid}")]
public async Task GetClient(Guid id)
{
try
{
var config = await _configManager.GetConfigurationAsync();
var client = config.GetClientConfig(id);
if (client == null)
{
return NotFound(new { Message = $"Client with ID '{id}' not found" });
}
return Ok(client);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving download client {id}", id);
return StatusCode(500, new { Error = "An error occurred while retrieving the download client" });
}
}
///
/// Adds a new download client
///
[HttpPost]
public async Task AddClient([FromBody] ClientConfig clientConfig)
{
try
{
// Validate the new client configuration
clientConfig.Validate();
// Get the current configuration
var config = await _configManager.GetConfigurationAsync();
// Check if a client with the same ID already exists
if (config.GetClientConfig(clientConfig.Id) != null)
{
return BadRequest(new { Error = $"A client with ID '{clientConfig.Id}' already exists" });
}
// Add the new client
config.Clients.Add(clientConfig);
// Persist the updated configuration
var result = await _configManager.SaveConfigurationAsync(config);
if (!result)
{
return StatusCode(500, new { Error = "Failed to save download client configuration" });
}
_logger.LogInformation("Added new download client: {name} ({id})", clientConfig.Name, clientConfig.Id);
return CreatedAtAction(nameof(GetClient), new { id = clientConfig.Id }, clientConfig);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding download client");
return BadRequest(new { Error = ex.Message });
}
}
///
/// Updates an existing download client
///
[HttpPut("{id:guid}")]
public async Task UpdateClient(Guid id, [FromBody] ClientConfig clientConfig)
{
try
{
// Ensure the ID in the route matches the ID in the body
if (id != clientConfig.Id)
{
return BadRequest(new { Error = "Client ID in the URL does not match the ID in the request body" });
}
// Validate the updated client configuration
clientConfig.Validate();
// Get the current configuration
var config = await _configManager.GetConfigurationAsync();
// Find the client to update
var existingClientIndex = config.Clients.FindIndex(c => c.Id == id);
if (existingClientIndex == -1)
{
return NotFound(new { Message = $"Client with ID '{id}' not found" });
}
// Update the client
config.Clients[existingClientIndex] = clientConfig;
// Persist the updated configuration
var result = await _configManager.SaveConfigurationAsync(config);
if (!result)
{
return StatusCode(500, new { Error = "Failed to save download client configuration" });
}
_logger.LogInformation("Updated download client: {name} ({id})", clientConfig.Name, clientConfig.Id);
return Ok(clientConfig);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating download client {id}", id);
return BadRequest(new { Error = ex.Message });
}
}
///
/// Deletes a download client
///
[HttpDelete("{id:guid}")]
public async Task DeleteClient(Guid id)
{
try
{
// Get the current configuration
var config = await _configManager.GetConfigurationAsync();
// Find the client to delete
var existingClientIndex = config.Clients.FindIndex(c => c.Id == id);
if (existingClientIndex == -1)
{
return NotFound(new { Message = $"Client with ID '{id}' not found" });
}
// Remove the client
config.Clients.RemoveAt(existingClientIndex);
// Persist the updated configuration
var result = await _configManager.SaveConfigurationAsync(config);
if (!result)
{
return StatusCode(500, new { Error = "Failed to save download client configuration" });
}
_logger.LogInformation("Deleted download client with ID: {id}", id);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting download client {id}", id);
return StatusCode(500, new { Error = "An error occurred while deleting the download client" });
}
}
///
/// Tests connection to a download client
///
[HttpPost("{id:guid}/test")]
public async Task TestConnection(Guid id)
{
try
{
// Get the client configuration
var config = await _configManager.GetConfigurationAsync();
var clientConfig = config.GetClientConfig(id);
if (clientConfig == null)
{
return NotFound(new { Message = $"Client with ID '{id}' not found" });
}
// Ensure the client is initialized
try
{
// Get the client instance
var client = _clientFactory.GetClient(id);
// Try to login
await client.LoginAsync();
_logger.LogInformation("Successfully connected to download client: {name} ({id})", clientConfig.Name, id);
return Ok(new { Success = true, Message = "Connection successful" });
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to connect to download client: {name} ({id})", clientConfig.Name, id);
return Ok(new { Success = false, Message = $"Connection failed: {ex.Message}" });
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error testing connection to download client {id}", id);
return StatusCode(500, new { Error = "An error occurred while testing the connection" });
}
}
///
/// Gets all clients of a specific type
///
[HttpGet("type/{type}")]
public async Task GetClientsByType(DownloadClientType type)
{
try
{
var config = await _configManager.GetConfigurationAsync();
var clients = config.Clients.Where(c => c.Type == type).ToList();
return Ok(clients);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving download clients of type {type}", type);
return StatusCode(500, new { Error = "An error occurred while retrieving download clients" });
}
}
}