global using System; global using System.Collections.Generic; global using System.Text; global using System.Text.Json; global using System.Threading; global using System.Threading.Tasks; global using DTLib.Demystifier; global using DTLib.Filesystem; global using DTLib.Logging; global using ParadoxSaveParser.Lib; global using Directory = DTLib.Filesystem.Directory; global using File = DTLib.Filesystem.File; global using Path = DTLib.Filesystem.Path; using DTLib.Console; using DTLib.Dtsod; using DTLib.Web; using DTLib.Web.Routes; using ParadoxSaveParser.WebAPI.BackgroundTasks; using ParadoxSaveParser.WebAPI.Database; using ParadoxSaveParser.WebAPI.Routes; using ParadoxSaveParser.WebAPI.SaveDataFilters; // ReSharper disable MethodHasAsyncOverload namespace ParadoxSaveParser.WebAPI; public static class Program { internal static bool IsDebug = true; internal static DatabaseConnector DB = null!; public static async Task Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; Console.CursorVisible = false; #if DEBUG IsDebug = true; #endif new LaunchArgumentParser( new LaunchArgument(["-d", "--debug"], "enables debug log output to console", () => IsDebug = true) ).AllowNoArguments().ParseAndHandle(args); var loggerRoot = new CompositeLogger( new ConsoleLogger { DebugLogEnabled = IsDebug }, new FileLogger("logs", "ParadoxSaveParser.WebAPI") { DebugLogEnabled = true }); var loggerMain = new ContextLogger(nameof(Main), loggerRoot); loggerMain.LogDebug("Debug log is enabled"); CancellationTokenSource mainCancel = new(); Console.CancelKeyPress += (_, e) => { e.Cancel = true; loggerMain.LogInfo("Ctrl+C Pressed"); mainCancel.Cancel(); }; try { // config IOPath configPath = "./config.dtsod"; Config config; if (File.Exists(configPath)) { config = Config.FromDtsod(new DtsodV23(File.ReadAllText(configPath))); } else { loggerMain.LogWarn("config file not found."); config = new(); File.WriteAllText(configPath, config.ToString()); loggerMain.LogWarn($"created default at {configPath}."); } PathHelper.CreateProgramDirectories(); PathHelper.CleanTempDirectory(); DB = new("database.sqlite", 30, loggerRoot); await DB.InitializeAsync(); await DB.DeleteInvalidData(); var bgJobManager = new BackgroundJobManager(loggerRoot); var saveFilters = new Dictionary { { Game.EU4, new SaveDataFilterEU4() }, }; // http server var router = new SimpleRouter(loggerRoot); router.DefaultRoute = new SimpleRouter.RouteWithMethod(HttpMethod.GET, new ServeFilesRouteHandler("public")); router.MapRoute("/uploadSave", HttpMethod.POST, new UploadSaveHandler(mainCancel.Token, bgJobManager, saveFilters)); router.MapRoute("/getSaveStatus", HttpMethod.GET, new GetSaveStatusHandler(mainCancel.Token)); router.MapRoute("/getSaveData", HttpMethod.GET, new GetSaveDataHandler(mainCancel.Token)); var app = new WebApp(config.BaseUrl, loggerRoot, router, mainCancel.Token); await app.Run(); } catch (OperationCanceledException ex) { loggerMain.LogWarn($"catched OperationCanceledException from {ex.Source}"); } catch (Exception ex) { loggerMain.LogError(ex.ToStringDemystified()); } } }