using System.Collections.Concurrent; using Common.Configuration.DownloadClient; using Common.Enums; using Infrastructure.Configuration; using Infrastructure.Http; using Infrastructure.Interceptors; using Infrastructure.Verticals.ContentBlocker; using Infrastructure.Verticals.DownloadClient.Deluge; using Infrastructure.Verticals.DownloadClient.QBittorrent; using Infrastructure.Verticals.DownloadClient.Transmission; using Infrastructure.Verticals.Files; using Infrastructure.Verticals.ItemStriker; using Infrastructure.Verticals.Notifications; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Infrastructure.Verticals.DownloadClient.Factory; /// /// Factory for creating and managing download client service instances /// public class DownloadClientFactory : IDownloadClientFactory { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly IConfigManager _configManager; private readonly ConcurrentDictionary _clients = new(); public DownloadClientFactory( ILogger logger, IServiceProvider serviceProvider, IConfigManager configManager) { _logger = logger; _serviceProvider = serviceProvider; _configManager = configManager; } /// public IDownloadService GetClient(Guid clientId) { if (clientId == Guid.Empty) { throw new ArgumentException("Client ID cannot be empty", nameof(clientId)); } return _clients.GetOrAdd(clientId, CreateClient); } /// public IEnumerable GetAllEnabledClients() { var downloadClientConfig = _configManager.GetConfiguration(); foreach (var client in downloadClientConfig.GetEnabledClients()) { yield return GetClient(client.Id); } } /// public IEnumerable GetClientsByType(DownloadClientType clientType) { var downloadClientConfig = _configManager.GetConfiguration(); foreach (var client in downloadClientConfig.GetEnabledClients().Where(c => c.Type == clientType)) { yield return GetClient(client.Id); } } /// public void RefreshClient(Guid clientId) { if (_clients.TryRemove(clientId, out var service)) { service.Dispose(); _logger.LogDebug("Removed client {clientId} from cache", clientId); } // Re-create and add the client _clients[clientId] = CreateClient(clientId); _logger.LogDebug("Re-created client {clientId}", clientId); } /// public void RefreshAllClients() { _logger.LogInformation("Refreshing all download clients"); // Get list of client IDs to avoid modifying collection during iteration var clientIds = _clients.Keys.ToList(); foreach (var clientId in clientIds) { RefreshClient(clientId); } } private IDownloadService CreateClient(Guid clientId) { var downloadClientConfig = _configManager.GetConfiguration(); var clientConfig = downloadClientConfig.GetClientConfig(clientId); if (clientConfig == null) { throw new Exception($"No configuration found for client with ID {clientId}"); } IDownloadService service = clientConfig.Type switch { DownloadClientType.QBittorrent => CreateQBitService(clientConfig), DownloadClientType.Transmission => CreateTransmissionService(clientConfig), DownloadClientType.Deluge => CreateDelugeService(clientConfig), _ => throw new NotSupportedException($"Download client type {clientConfig.Type} is not supported") }; // Initialize the service with its configuration service.Initialize(clientConfig); _logger.LogInformation("Created client {clientName} ({clientId}) of type {clientType}", clientConfig.Name, clientId, clientConfig.Type); return service; } private QBitService CreateQBitService(ClientConfig clientConfig) { var client = _serviceProvider.GetRequiredService(); client.Initialize(clientConfig); return client; } private TransmissionService CreateTransmissionService(ClientConfig clientConfig) { var client = _serviceProvider.GetRequiredService(); client.Initialize(clientConfig); return client; } private DelugeService CreateDelugeService(ClientConfig clientConfig) { var client = _serviceProvider.GetRequiredService(); client.Initialize(clientConfig); return client; } }