using AZKiServer.Models; namespace AZKiServer.Services; public class FileScannerService(MediaService mediaService, IConfiguration config, ILogger logger) : IHostedService, IDisposable { private Timer? _timer; public void Dispose() { _timer?.Dispose(); } public Task StartAsync(CancellationToken cancellationToken) { var path = config["SCAN_LOCATION"]; if (string.IsNullOrWhiteSpace(path)) return Task.CompletedTask; _timer = new Timer((_) => { ScanFilesAsync(path).Wait(); }, null, TimeSpan.FromMinutes(0), TimeSpan.FromHours(1)); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Dispose(); return Task.CompletedTask; } private async Task ScanFilesAsync(string path) { logger.LogInformation("Scanning Files"); try { var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); var existingFiles = await mediaService.GetExistingFilePathsAsync(); var entries = new List(); foreach (var filePath in files) { var relativePath = Path.GetRelativePath(path, filePath); if (relativePath[0] == '.') //Ignore hidden folders continue; if (existingFiles.Contains(relativePath)) continue; var entry = MediaEntry.Parse(relativePath); if(entry.HasError) { logger.LogError(entry.Error.GetException(), "Failed to parse file data"); continue; } entries.Add(entry); } if(entries.Count > 0) { await mediaService.AddMediaBulkAsync(entries); logger.LogInformation("Added {count} file entries", entries.Count); } } catch (Exception ex) { logger.LogError(ex, "Failed to read directory contents"); } } }