From 43b22b62ddfc8b04b89f8dc119df4c9b08554baf Mon Sep 17 00:00:00 2001 From: MrDevBot Date: Tue, 1 Sep 2026 20:39:22 +1000 Subject: [PATCH] Use structured localized Discord embeds --- src/Program.cs | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Program.cs b/src/Program.cs index 4f0c57c..6925583 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,4 +1,5 @@ using System.Buffers.Binary; +using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Text; @@ -37,11 +38,14 @@ builder.Services.AddDiscordGateway(o => { o.Token = discordToken; o.Intents = Ga .AddApplicationCommands(); var host = builder.Build(); -InteractionMessageProperties Reply(string title, string text, int color, params (string Name, string Value)[] fields) +string Time(DateTimeOffset value) => $"\n"; +InteractionMessageProperties Reply(string title, string text, int color, params (string Name, string Value, bool Inline)[] fields) { - var embed = new EmbedProperties().WithTitle(title).WithDescription(text).WithColor(new(color)) - .WithTimestamp(DateTimeOffset.UtcNow).WithFooter(new EmbedFooterProperties().WithText("Beetlejuice • Project Zomboid")); - if (fields.Length > 0) embed.AddFields(fields.Select(x => new EmbedFieldProperties().WithName(x.Name).WithValue(x.Value).WithInline())); + var embed = new EmbedProperties().WithTitle(title).WithColor(new(color)) + .WithTimestamp(DateTimeOffset.UtcNow).WithFooter(new EmbedFooterProperties().WithText("Beetlejuice | Project Zomboid")); + if (text.Length > 0) embed.WithDescription(text); + if (fields.Length > 0) embed.AddFields(fields.Select(x => + new EmbedFieldProperties().WithName(x.Name).WithValue(x.Value).WithInline(x.Inline))); return new InteractionMessageProperties().AddEmbeds(embed).WithFlags(MessageFlags.Ephemeral); } InteractionMessageProperties Denied(string text = "You are not authorised to use this command.") => Reply("⛔ Access denied", text, 0xED4245); @@ -57,7 +61,8 @@ InteractionMessageProperties Whitelist(ApplicationCommandContext c, User user, b string temp = whitelistPath + ".tmp"; File.WriteAllLines(temp, whitelist.Order().Select(x => x.ToString())); File.Move(temp, whitelistPath, true); - return Reply("✅ Whitelist updated", $"{(add ? "Added" : "Removed")} <@{user.Id}>.", 0x57F287, ("Action", add ? "Added" : "Removed")); + return Reply("Whitelist updated", "Access control was updated successfully.", 0x57F287, + ("User", $"<@{user.Id}>\n`{user.Id}`", true), ("Action", add ? "`ADDED`" : "`REMOVED`", true)); } } async Task Command(string command, bool allowDisconnect = false) @@ -130,14 +135,14 @@ async Task Manual() return Reply("⏱️ Restart cooldown", $"Try again in {Math.Ceiling((cooldown - (DateTimeOffset.UtcNow - last)).TotalSeconds)} seconds.", 0xFEE75C); int count = (await Players()).Count; if (count == 0) count = (await Players()).Count; - if (count != 0) return Reply("🛑 Restart denied", "The server cannot restart while players are connected.", 0xED4245, - ("Players online", count.ToString())); + if (count != 0) return Reply("Restart denied", "The server cannot restart while players are connected.", 0xED4245, + ("Players Online", $"`{count}`", true)); await Quit(); lastManual = DateTimeOffset.UtcNow; release = false; _ = Task.Run(async () => { try { await Ready("Manual"); } finally { gate.Release(); } }); - return Reply("🔄 Restart initiated", "No players are online. The server is restarting safely.", 0x57F287, - ("Cooldown", "10 minutes")); + return Reply("Restart initiated", "The server is restarting safely.", 0x57F287, + ("Requested", Time(DateTimeOffset.UtcNow), false), ("Cooldown Ends", Time(DateTimeOffset.UtcNow + cooldown), false)); } catch (Exception e) { return Reply("❌ Restart unavailable", e.Message, 0xED4245); } finally { if (release) gate.Release(); } @@ -198,20 +203,24 @@ async Task Status() { try { - int count = (await Players()).Count; - return Reply("Project Zomboid", "The server is online and responding.", 0x57F287, - ("Status", "🟢 Online"), ("Players", count == 0 ? "None" : count.ToString())); + long started = Stopwatch.GetTimestamp(); + await Command("list"); + long latency = (long)Stopwatch.GetElapsedTime(started).TotalMilliseconds; + return Reply("Online", "", 0x57F287, + ("Response Time", $"`{latency} ms`", true), ("Next Restart", Time(Next()), false)); } - catch { return Reply("Project Zomboid", "The server is offline, restarting, or unreachable.", 0xED4245, ("Status", "🔴 Unavailable")); } + catch { return Reply("Unavailable", "The server is offline, restarting, or unreachable.", 0xED4245); } } async Task PlayerList() { try { var p = await Players(); - return Reply("👥 Online players", p.Count == 0 ? "The server is currently empty." : p.Names.Length == 0 - ? "Player names are unavailable." : string.Join("\n", p.Names.Select(x => $"• **{x}**")), 0x5865F2, - ("Count", p.Count.ToString())); + if (p.Count == 0) return Reply("Online players", "", 0x5865F2, ("Connected", "`0`", true)); + string names = p.Names.Length == 0 ? "Names unavailable." : + string.Join("\n", p.Names.Take(25).Select((name, index) => $"`{index + 1:00}` **{name}**")); + return Reply("Online players", "", 0x5865F2, + ("Connected", $"`{p.Count}`", true), ("Players", names, false)); } catch { return Reply("❌ Player query failed", "Unable to reach the Project Zomboid server.", 0xED4245); } }