using Npgsql; using Serilog; using System; using System.Collections.Generic; using System.IO; using System.Text.Json; using System.Threading.Tasks; namespace TvSyncApp { public class Program { public static async Task Main(string[] args) { string settingsPath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"); var settings = TvSyncApp.Settings.Load(settingsPath) ?? throw new Exception("Failed to load settings from appsettings.json"); Console.WriteLine($"Log level: {settings.Global.LogLevel}"); Console.WriteLine($"Database type: {settings.Database.DbType}"); // Console.WriteLine($"TVMaze series API: {settings.Json.SeriesApi}"); string rootDir = Directory.GetCurrentDirectory(); var directories = new Dictionary { ["SERIESDIR"] = Path.Combine(rootDir, "cache", "series"), ["EPISODEDIR"] = Path.Combine(rootDir, "cache", "episodes"), ["CASTDIR"] = Path.Combine(rootDir, "cache", "cast"), // ["GUESTCASTDIR"] = Path.Combine(rootDir, "cache", "guestcast"), ["CREWDIR"] = Path.Combine(rootDir, "cache", "crew"), ["UNKNOWN"] = Path.Combine(rootDir, "cache", "unknown") }; CreateDirectories(rootDir); Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .WriteTo.File(Path.Combine(rootDir, "log", "sync.log")) .CreateLogger(); Log.Information("Starting sync process..."); // --- Fetch series IDs from PostgreSQL --- string connectionString = $"Host={settings.DbSettings.Hostname};Port={settings.DbSettings.PgsqlPort};Username={settings.DbSettings.PgsqlUsername};Password={settings.DbSettings.PgsqlPassword};Database={settings.DbSettings.DbName}"; List seriesUpdates = GetSeriesIdsFromDb(connectionString); List seriesIds = seriesUpdates .Select(x => x.SeriesId.ToString()) .ToList(); Log.Information("Fetched {Count} series IDs from tvupdates table.", seriesIds.Count); // Convert to string list if your Loader expects strings List updateList = seriesIds.ConvertAll(id => id.ToString()); // Optionally, you can also fetch timestamps if needed Dictionary updateDict = new Dictionary(); var loader = new Loader(); var result = await loader.LoadJsonAsync(directories, updateList, updateDict, settings); Log.Information("Sync complete. Success: {Success}, Failed: {Failed}", result.Success, result.Failed); Log.CloseAndFlush(); return 0; } private static List GetSeriesIdsFromDb(string connectionString) { var results = new List(); try { using var conn = new NpgsqlConnection(connectionString); conn.Open(); const string query = @" SELECT seriesid, timestamp FROM updates.tvupdates ORDER BY seriesid"; using var cmd = new NpgsqlCommand(query, conn); using var reader = cmd.ExecuteReader(); while (reader.Read()) { if (!reader.IsDBNull(0) && !reader.IsDBNull(1)) { results.Add(new SeriesUpdate { SeriesId = reader.GetInt32(0), Timestamp = long.Parse(reader.GetString(1)) }); } } SaveSeriesUpdatesToFile(results); } catch (Exception ex) { Log.Error(ex, "Failed to fetch series updates or manage JSON output."); } return results; } private static void SaveSeriesUpdatesToFile(List data) { string configDir = Path.Combine(AppContext.BaseDirectory, "config"); Directory.CreateDirectory(configDir); string fileName = "previous_tvmaze_updates.json"; string filePath = Path.Combine(configDir, fileName); if (File.Exists(filePath)) { string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss"); string archiveName = $"previous_tvmaze_updates_{timestamp}.json"; string archivePath = Path.Combine(configDir, archiveName); File.Move(filePath, archivePath); } var options = new JsonSerializerOptions { WriteIndented = true }; string json = JsonSerializer.Serialize(data, options); File.WriteAllText(filePath, json); var archives = Directory.GetFiles(configDir, "previous_tvmaze_updates_*.json") .Select(f => new FileInfo(f)) .OrderByDescending(f => f.CreationTimeUtc) .ToList(); foreach (var oldFile in archives.Skip(5)) { oldFile.Delete(); } Log.Information("Saved {Count} series updates to {FilePath}", data.Count, filePath); } private static void CreateDirectories(string rootDir) { Directory.CreateDirectory(Path.Combine(rootDir, "log")); Directory.CreateDirectory(Path.Combine(rootDir, "temp")); Directory.CreateDirectory(Path.Combine(rootDir, "cache", "series")); Directory.CreateDirectory(Path.Combine(rootDir, "cache", "episodes")); Directory.CreateDirectory(Path.Combine(rootDir, "cache", "cast")); Directory.CreateDirectory(Path.Combine(rootDir, "cache", "guestcast")); Directory.CreateDirectory(Path.Combine(rootDir, "cache", "crew")); } } public class SeriesUpdate { public int SeriesId { get; set; } public long Timestamp { get; set; } } }