using System.Net; using DotBased.Logging; using DotBased.Monads; using Manager.Data.Entities.LibraryContext; using Manager.YouTube; namespace Manager.App.Services.System; public class ClientService(IServiceScopeFactory scopeFactory, ILogger logger) : ExtendedBackgroundService(nameof(ClientService), "Managing YouTube clients", logger, TimeSpan.FromMinutes(10)) { private readonly YouTubeClientCollection _loadedClients = []; private ILibraryService? _libraryService; protected override Task InitializeAsync(CancellationToken stoppingToken) { stoppingToken.Register(CancellationRequested); using var scope = scopeFactory.CreateScope(); _libraryService = scope.ServiceProvider.GetRequiredService(); LogEvent("Initializing service..."); return Task.CompletedTask; } protected override async Task ExecuteServiceAsync(CancellationToken stoppingToken) { LogEvent($"Saving {_loadedClients.Count} loaded client(s)"); foreach (var client in _loadedClients) { await SaveClientAsync(client, cancellationToken: stoppingToken); } } private async void CancellationRequested() { foreach (var client in _loadedClients) { await SaveClientAsync(client); client.Dispose(); } } public async Task AddClientByIdAsync(string id, CancellationToken stoppingToken = default) { if (_libraryService == null) { return ResultError.Fail("Library service is not initialized!."); } var clientResult = await _libraryService.GetChannelByIdAsync(id, stoppingToken); if (!clientResult.IsSuccess) { return clientResult; } var clientAcc = clientResult.Value.ClientAccount; if (clientAcc == null) { return ResultError.Fail("Client account is not initialized!."); } var cookieCollection = new CookieCollection(); foreach (var httpCookie in clientAcc.HttpCookies) { var cookie = new Cookie { Name = httpCookie.Name, Value = httpCookie.Value, Domain = httpCookie.Domain, Path = httpCookie.Path, Secure = httpCookie.Secure, HttpOnly = httpCookie.HttpOnly, Expires = httpCookie.ExpiresUtc ?? DateTime.MinValue }; cookieCollection.Add(cookie); } var ytClientResult = await YouTubeClient.CreateAsync(cookieCollection, clientAcc.UserAgent ?? ""); if (!ytClientResult.IsSuccess) { return ytClientResult; } AddClient(ytClientResult.Value); return Result.Success(); } public void AddClient(YouTubeClient client) { if (_loadedClients.Contains(client)) { return; } _loadedClients.Add(client); } public async Task SaveClientAsync(YouTubeClient client, CancellationToken cancellationToken = default) { if (_libraryService == null) { return ResultError.Fail("Library service is not initialized!."); } if (string.IsNullOrWhiteSpace(client.Id)) { LogEvent("Failed to store client no ID!", LogSeverity.Warning); return ResultError.Fail("Client does not have an ID, cannot save to library database!"); } var saveResult = await _libraryService.SaveClientAsync(new ClientAccountEntity { Id = client.Id, UserAgent = client.UserAgent }, cancellationToken); return saveResult; } }