Auto-Update wie beim MSCO Launcher
Beim Start installiert sich ein neuer Launcher sofort selbst (Fortschrittsfenster, Neustart), neue BSO-Versionen kommen nach dem Anmelden - beides abschaltbar. Einstellungen: Nach Updates suchen / Installieren und neu starten. Updates wieder nur von der Website; dotnet publish laedt hoch (release.ps1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+2
-10
@@ -75,16 +75,8 @@ public static class Api
|
||||
// --- Freunde und Lobby (alles mit dem Konto-Token)
|
||||
public static Task<Result> Get(string path, string token) => Send(HttpMethod.Get, path, null, token);
|
||||
public static Task<Result> Post(string path, string token, object? body = null) => Send(HttpMethod.Post, path, body ?? new { }, token);
|
||||
/// <summary>Gegen eine Test-Website (-dev, BSO_LAUNCHER_API)? Dann kommen Releases zuerst von dort.</summary>
|
||||
public static bool TestWebsite => Base != BaseUrl.TrimEnd('/');
|
||||
|
||||
/// <summary>Neueste Version: vom Git-Server (Gitea-Releases), sonst von der Website - mit -dev umgekehrt.</summary>
|
||||
public static async Task<Release?> Latest(string product) =>
|
||||
TestWebsite
|
||||
? await WebsiteLatest(product) ?? await GiteaReleases.Latest(product)
|
||||
: await GiteaReleases.Latest(product) ?? await WebsiteLatest(product);
|
||||
|
||||
static async Task<Release?> WebsiteLatest(string product)
|
||||
/// <summary>Neueste Version von mod/launcher auf der Website (wie beim MSCO Keymaster) - oder null.</summary>
|
||||
public static async Task<Release?> Latest(string product)
|
||||
{
|
||||
var r = await Send(HttpMethod.Get, "/api/releases/latest?product=" + product, null, null);
|
||||
if (!r.Ok) return null;
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BSO.Launcher;
|
||||
|
||||
/// <summary>
|
||||
/// Releases direkt vom Git-Server (git.mbm.wtf, Gitea): Mod aus BSO-Mod, Launcher aus BSO-Launcher (beide oeffentlich).
|
||||
/// Jedes Release hat die Datei und bso-release.json (Version, SHA-256, Signatur aus release.ps1) - installiert wird weiter
|
||||
/// nur, was mit dem BSO-Release-Schluessel signiert ist, egal woher die Datei kommt.
|
||||
/// </summary>
|
||||
public static class GiteaReleases
|
||||
{
|
||||
public const string ApiBase = "https://git.mbm.wtf/api/v1/repos/MrMaho/";
|
||||
public const string ManifestName = "bso-release.json";
|
||||
|
||||
static string Repo(string product) => product == "launcher" ? "BSO-Launcher" : "BSO-Mod";
|
||||
|
||||
sealed record Manifest(string product, string version, string sha256, long size, string file, string signature);
|
||||
|
||||
/// <summary>Version aus dem Tag ("v0.5.0" -> "0.5.0") oder null.</summary>
|
||||
static string? TagVersion(JsonElement release)
|
||||
{
|
||||
string tag = release.GetProperty("tag_name").GetString() ?? "";
|
||||
string v = tag.TrimStart('v', 'V');
|
||||
return Version.TryParse(v, out _) ? v : null;
|
||||
}
|
||||
|
||||
static bool Published(JsonElement release) =>
|
||||
!release.GetProperty("draft").GetBoolean() && !release.GetProperty("prerelease").GetBoolean();
|
||||
|
||||
static async Task<JsonElement[]> Fetch(string product)
|
||||
{
|
||||
using var doc = JsonDocument.Parse(await Api.Http.GetStringAsync(ApiBase + Repo(product) + "/releases?limit=20"));
|
||||
return doc.RootElement.EnumerateArray().Where(Published).Select(r => r.Clone()).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>Neueste Version von mod/launcher - null, wenn es keine gibt oder Gitea nicht erreichbar ist.</summary>
|
||||
public static async Task<Api.Release?> Latest(string product)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newest = (await Fetch(product))
|
||||
.Select(r => (release: r, version: TagVersion(r)))
|
||||
.Where(x => x.version != null)
|
||||
.OrderByDescending(x => Version.Parse(x.version!))
|
||||
.FirstOrDefault();
|
||||
if (newest.version == null) return null;
|
||||
|
||||
var assets = newest.release.GetProperty("assets").EnumerateArray()
|
||||
.ToDictionary(a => a.GetProperty("name").GetString() ?? "", a => a.GetProperty("browser_download_url").GetString() ?? "");
|
||||
if (!assets.TryGetValue(ManifestName, out string? manifestUrl)) return null;
|
||||
var m = JsonSerializer.Deserialize<Manifest>(await Api.Http.GetStringAsync(manifestUrl));
|
||||
if (m == null || m.product != product || !assets.TryGetValue(m.file, out string? fileUrl)) return null;
|
||||
return new Api.Release(product, m.version, m.sha256, m.size, newest.release.GetProperty("body").GetString() ?? "",
|
||||
newest.release.GetProperty("published_at").GetString() ?? "", m.file, fileUrl, m.signature);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LauncherLog.Error($"Gitea-Release {product}: {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Neuigkeiten: Releases von Mod und Launcher, neueste zuerst. null = Gitea nicht erreichbar.</summary>
|
||||
public static async Task<List<object>?> List()
|
||||
{
|
||||
var items = new List<(DateTimeOffset date, object item)>();
|
||||
int reached = 0;
|
||||
foreach (string product in new[] { "mod", "launcher" })
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var r in await Fetch(product))
|
||||
{
|
||||
if (TagVersion(r) is not { } version) continue;
|
||||
string date = r.GetProperty("published_at").GetString() ?? "";
|
||||
items.Add((DateTimeOffset.TryParse(date, out var d) ? d : default,
|
||||
new { product, version, changelog = r.GetProperty("body").GetString() ?? "", date }));
|
||||
}
|
||||
reached++;
|
||||
}
|
||||
catch (Exception e) { LauncherLog.Error($"Gitea-Releases {product}: {e.Message}"); }
|
||||
}
|
||||
return reached == 0 ? null : items.OrderByDescending(x => x.date).Select(x => x.item).ToList();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public sealed class Settings
|
||||
public bool AutoConnect { get; set; } = true;
|
||||
public bool KeepOpen { get; set; }
|
||||
public bool AutoUpdateMod { get; set; } = true;
|
||||
/// <summary>Beim Start eine neue Launcher-Version gleich installieren und neu starten (wie beim MSCO Launcher).</summary>
|
||||
public bool AutoUpdateLauncher { get; set; } = true;
|
||||
/// <summary>"de" oder "en" - null = nach der Windows-Sprache (Lang.Default).</summary>
|
||||
public string? Language { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user