Web API code fix

This commit is contained in:
Timerix 2025-03-20 13:40:43 +05:00
parent 68ae9540ad
commit 1fa3e4eb6e
3 changed files with 87 additions and 33 deletions

View File

@ -11,4 +11,8 @@
<ProjectReference Include="..\ParadoxSaveParser.Lib\ParadoxSaveParser.Lib.csproj" /> <ProjectReference Include="..\ParadoxSaveParser.Lib\ParadoxSaveParser.Lib.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="DTLib.Demystifier" Version="1.1.0" />
</ItemGroup>
</Project> </Project>

View File

@ -1,6 +0,0 @@
@ParadoxSaveParser.WebAPI_HostAddress = http://localhost:5226
GET {{ParadoxSaveParser.WebAPI_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -2,12 +2,10 @@ global using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using DTLib.Demystifier;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ParadoxSaveParser.Lib; using ParadoxSaveParser.Lib;
@ -15,62 +13,120 @@ namespace ParadoxSaveParser.WebAPI;
public enum SaveFileProcessingStatus public enum SaveFileProcessingStatus
{ {
NotFound, Uploading, Parsing, SavingResults, Done, Error Initialized, Uploading, Parsing, SavingResults, Done, Error
}
public enum Game
{
Unknown, EU4
} }
public class SaveFileMetadata public class SaveFileMetadata
{ {
public required string guid; public required string id { get; init; }
public required Game game { get; init; }
public required SaveFileProcessingStatus status { get; set; } public required SaveFileProcessingStatus status { get; set; }
public string? errorMesage { get; set; }
private static readonly JsonSerializerOptions _jsonOptions = new() { WriteIndented = true };
public void SaveToFile()
{
using var metaFile = File.Open(PathHelper.GetMetaFilePath(id), FileMode.CreateNew, FileAccess.Write);
JsonSerializer.Serialize(metaFile, this, _jsonOptions);
}
}
public static class PathHelper
{
public const string DATA_DIR = "data";
public static string SAVES_DIR = Path.Join(DATA_DIR, "saves");
public static string GetMetaFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".meta.json");
public static string GetEU4SaveFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".eu4");
} }
public class Program public class Program
{ {
private const string DATA_DIR = "data";
private static string SAVES_DIR = Path.Join(DATA_DIR, "saves");
private static ConcurrentDictionary<string, SaveFileMetadata> _saveMetadataStorage = new(); private static ConcurrentDictionary<string, SaveFileMetadata> _saveMetadataStorage = new();
private static WebApplication _app = null!;
public static void Main(string[] args) public static void Main(string[] args)
{ {
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var app = builder.Build(); _app = builder.Build();
foreach (var metaFilePath in Directory.GetFiles(SAVES_DIR, "*.meta.json", SearchOption.TopDirectoryOnly)) foreach (var metaFilePath in Directory.GetFiles(PathHelper.SAVES_DIR, "*.meta.json", SearchOption.TopDirectoryOnly))
{ {
using var metaFile = File.Open(metaFilePath, FileMode.Open, FileAccess.Read); using var metaFile = File.Open(metaFilePath, FileMode.Open, FileAccess.Read);
var meta = JsonSerializer.Deserialize<SaveFileMetadata>(metaFile) ?? throw new NullReferenceException(metaFilePath); var meta = JsonSerializer.Deserialize<SaveFileMetadata>(metaFile) ?? throw new NullReferenceException(metaFilePath);
if (meta.status != SaveFileProcessingStatus.Done) if (meta.status != SaveFileProcessingStatus.Done)
{ {
app.Logger.Log(LogLevel.Warning, $"metadata file '{metaFilePath}' status has invalid status {meta.status}")); _app.Logger.Log(LogLevel.Warning, "metadata file '{metaFilePath}' status has invalid status {status}", metaFilePath, meta.status);
} }
if(!_saveMetadataStorage.TryAdd(meta.guid, meta)) if(!_saveMetadataStorage.TryAdd(meta.id, meta))
throw new Exception("Guid collision!"); throw new Exception("Guid collision!");
} }
app.UseHttpsRedirection(); _app.UseHttpsRedirection();
app.MapPost("/parse/eu4", async httpContext => _app.MapPost("/parse/eu4", (HttpContext httpContext) =>
{ {
var remoteFile = httpContext.Request.Form.Files.FirstOrDefault(); var remoteFile = httpContext.Request.Form.Files.FirstOrDefault();
if(remoteFile is null) if(remoteFile is null || !remoteFile.FileName.EndsWith(".eu4"))
return; throw new Exception($"Invalid file format: {remoteFile?.FileName}");
string save_id = Guid.NewGuid().ToString();
string meta_file_path = Path.Join(SAVES_DIR, save_id + ".meta.json"); string saveId = Guid.NewGuid().ToString();
// string save_file_path = Path.Join(SAVES_DIR, save_id + ".eu4"); string metaFilePath = PathHelper.GetMetaFilePath(saveId);
// await using var metaFile = File.Open(meta_file_path, FileMode.CreateNew, FileAccess.Write); if (File.Exists(metaFilePath))
if (File.Exists(meta_file_path))
{ {
httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
throw new Exception($"Guid collision! file {meta_file_path} already exists.") throw new Exception($"Guid collision! file {metaFilePath} already exists.");
}
var meta = new SaveFileMetadata
{
id = saveId,
game = Game.EU4,
status = SaveFileProcessingStatus.Initialized,
};
if (!_saveMetadataStorage.TryAdd(saveId, meta))
{
throw new Exception($"Guid collision! Can't create metadata with id {saveId}");
} }
await using var saveFile = BeginEU4SaveParse(remoteFile, meta);
await remoteFile.OpenReadStream().CopyToAsync(); return meta;
var parser = new ParserEU4(stream);
}); });
app.Run(); _app.Run();
}
private static async void BeginEU4SaveParse(IFormFile remoteFile, SaveFileMetadata meta)
{
try
{
meta.status = SaveFileProcessingStatus.Uploading;
string saveFilePath = PathHelper.GetEU4SaveFilePath(meta.id);
await using var saveFile = File.Open(saveFilePath, FileMode.CreateNew, FileAccess.ReadWrite);
await using (var remoteStream = remoteFile.OpenReadStream())
{
await remoteStream.CopyToAsync(saveFile);
}
meta.status = SaveFileProcessingStatus.Parsing;
saveFile.Seek(0, SeekOrigin.Begin);
var parser = new ParserEU4(saveFile);
//var result = parser.Parse();
meta.status = SaveFileProcessingStatus.SavingResults;
// save
meta.status = SaveFileProcessingStatus.Done;
}
catch (Exception ex)
{
meta.status = SaveFileProcessingStatus.Error;
string errorMesage = ex.ToStringDemystified();
_app.Logger.Log(LogLevel.Error, "EU4SaveParse Error: {errorMesage}", errorMesage);
}
} }
} }