Files
2026-10-16 23:33:13 -07:00

158 lines
4.7 KiB
C#

using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace RadicadeServer.API.Launcher
{
[Route("api/launcher")]
public class LauncherBuildAPI : Controller
{
private static readonly string LauncherDirectory = Path.GetFullPath("./Launcher");
private static readonly string LauncherManifestPath = Path.Join(LauncherDirectory, "manifest.json");
private static async Task<JsonObject?> LoadLauncherManifest()
{
if (!System.IO.File.Exists(LauncherManifestPath))
return null;
var raw = await System.IO.File.ReadAllTextAsync(LauncherManifestPath);
return JsonNode.Parse(raw)?.AsObject();
}
private static string? GetString(JsonObject manifest, string key)
{
return manifest[key]?.GetValue<string>();
}
private static string? GetNestedString(JsonObject manifest, string parentKey, string childKey)
{
return manifest[parentKey]?[childKey]?.GetValue<string>();
}
private static bool GetBool(JsonObject manifest, string key, bool fallback = false)
{
return manifest[key]?.GetValue<bool>() ?? fallback;
}
private static IActionResult MissingManifestFile()
{
return new JsonResult(new
{
error = "Launcher manifest file was not found.",
path = LauncherManifestPath
})
{
StatusCode = StatusCodes.Status404NotFound
};
}
private static IActionResult InvalidManifestFile(string message, object? extra = null)
{
return new JsonResult(new
{
error = message,
path = LauncherManifestPath,
extra
})
{
StatusCode = StatusCodes.Status503ServiceUnavailable
};
}
[HttpGet("approved-build")]
public async Task<IActionResult> GetApprovedBuild()
{
if (!System.IO.File.Exists(LauncherManifestPath))
return MissingManifestFile();
try
{
var raw = await System.IO.File.ReadAllTextAsync(LauncherManifestPath);
var manifest = JsonNode.Parse(raw)?.AsObject();
if (manifest == null)
return InvalidManifestFile("Launcher manifest file is not a JSON object.");
var gameVersion = GetString(manifest, "version");
var manifestVersion = GetString(manifest, "manifestVersion");
var gameDownloadUrl = GetNestedString(manifest, "package", "url");
var packageSha256 = GetNestedString(manifest, "package", "sha256");
if (string.IsNullOrWhiteSpace(gameVersion) ||
string.IsNullOrWhiteSpace(manifestVersion) ||
string.IsNullOrWhiteSpace(gameDownloadUrl) ||
string.IsNullOrWhiteSpace(packageSha256))
{
return InvalidManifestFile(
"Approved build metadata is incomplete.",
new
{
missing = new[]
{
string.IsNullOrWhiteSpace(gameVersion) ? "version" : null,
string.IsNullOrWhiteSpace(manifestVersion) ? "manifestVersion" : null,
string.IsNullOrWhiteSpace(gameDownloadUrl) ? "package.url" : null,
string.IsNullOrWhiteSpace(packageSha256) ? "package.sha256" : null
}.Where(x => x != null).ToArray()
});
}
return Ok(new
{
gameVersion,
manifestVersion,
gameDownloadUrl,
packageSha256,
required = GetBool(manifest, "required", true),
launchTicket = GetString(manifest, "launchTicket"),
launchTicketRequired = GetBool(manifest, "launchTicketRequired"),
launchTicketUrl = GetString(manifest, "launchTicketUrl"),
launchTicketAudience = GetString(manifest, "launchTicketAudience"),
launchTicketNonce = GetString(manifest, "launchTicketNonce")
});
}
catch (JsonException ex)
{
return InvalidManifestFile("Launcher manifest file contains invalid JSON.", new { details = ex.Message });
}
}
[HttpGet("manifest.json")]
public async Task<IActionResult> GetManifest()
{
if (!System.IO.File.Exists(LauncherManifestPath))
return MissingManifestFile();
try
{
var raw = await System.IO.File.ReadAllTextAsync(LauncherManifestPath);
var manifest = JsonNode.Parse(raw)?.AsObject();
if (manifest == null)
return InvalidManifestFile("Launcher manifest file is not a JSON object.");
var version = GetString(manifest, "version");
var packageUrl = GetNestedString(manifest, "package", "url");
if (string.IsNullOrWhiteSpace(version) || string.IsNullOrWhiteSpace(packageUrl))
{
return InvalidManifestFile(
"Launcher manifest file is missing required fields.",
new
{
missing = new[]
{
string.IsNullOrWhiteSpace(version) ? "version" : null,
string.IsNullOrWhiteSpace(packageUrl) ? "package.url" : null
}.Where(x => x != null).ToArray()
});
}
return Content(raw, "application/json");
}
catch (JsonException ex)
{
return InvalidManifestFile("Launcher manifest file contains invalid JSON.", new { details = ex.Message });
}
}
}
}