From aa8776bd2f7ad6a91a1412d13906420c280e6de5 Mon Sep 17 00:00:00 2001 From: MrDevBot Date: Tue, 1 Sep 2026 20:13:10 +1000 Subject: [PATCH] Use embedded slash command responses --- src/Program.cs | 58 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/Program.cs b/src/Program.cs index 162683a..bed7a28 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -9,6 +9,7 @@ using NetCord; using NetCord.Gateway; using NetCord.Hosting.Gateway; using NetCord.Hosting.Services.ApplicationCommands; +using NetCord.Rest; using NetCord.Services.ApplicationCommands; string Env(string key, string? fallback = null) => Environment.GetEnvironmentVariable(key) ?? fallback @@ -36,20 +37,23 @@ builder.Services.AddDiscordGateway(o => { o.Token = discordToken; o.Intents = Ga .AddApplicationCommands(); var host = builder.Build(); +InteractionMessageProperties Reply(string title, string text, int color) => new InteractionMessageProperties() + .AddEmbeds(new EmbedProperties().WithTitle(title).WithDescription(text).WithColor(new(color))) + .WithFlags(MessageFlags.Ephemeral); +InteractionMessageProperties Denied(string text = "You are not authorised to use this command.") => Reply("Access denied", text, 0xED4245); bool Allowed(ApplicationCommandContext c) { lock (whitelistLock) return whitelist.Contains(c.User.Id); } -string Whitelist(ApplicationCommandContext c, string discordId, bool add) +InteractionMessageProperties Whitelist(ApplicationCommandContext c, User user, bool add) { - if (c.User.Id != initialUser) return "Not authorised."; - if (!ulong.TryParse(discordId, out ulong id)) return "Invalid Discord ID."; - if (!add && id == initialUser) return "The whitelist owner cannot be removed."; + if (c.User.Id != initialUser) return Denied("Only the whitelist owner can manage access."); + if (!add && user.Id == initialUser) return Reply("Whitelist unchanged", "The whitelist owner cannot be removed.", 0xFEE75C); lock (whitelistLock) { - bool changed = add ? whitelist.Add(id) : whitelist.Remove(id); - if (!changed) return add ? "Already whitelisted." : "Not whitelisted."; + bool changed = add ? whitelist.Add(user.Id) : whitelist.Remove(user.Id); + if (!changed) return Reply("Whitelist unchanged", add ? $"<@{user.Id}> is already whitelisted." : $"<@{user.Id}> is not whitelisted.", 0xFEE75C); string temp = whitelistPath + ".tmp"; File.WriteAllLines(temp, whitelist.Order().Select(x => x.ToString())); File.Move(temp, whitelistPath, true); - return $"{(add ? "Added" : "Removed")} <@{id}>."; + return Reply("Whitelist updated", $"{(add ? "Added" : "Removed")} <@{user.Id}>.", 0x57F287); } } async Task Command(string command, bool allowDisconnect = false) @@ -112,23 +116,24 @@ async Task Ready(string kind) } Console.Error.WriteLine($"{kind} restart timed out waiting for readiness."); } -async Task Manual() +async Task Manual() { - if (!await gate.WaitAsync(0)) return "A restart is already in progress."; + if (!await gate.WaitAsync(0)) return Reply("Restart busy", "A restart is already in progress.", 0xFEE75C); bool release = true; try { - if (lastManual is { } last && DateTimeOffset.UtcNow - last < cooldown) return "Restart cooldown is active."; + if (lastManual is { } last && DateTimeOffset.UtcNow - last < cooldown) + 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 $"Denied: {count} player(s) online."; + if (count != 0) return Reply("Restart denied", $"{count} player{(count == 1 ? " is" : "s are")} online.", 0xED4245); await Quit(); lastManual = DateTimeOffset.UtcNow; release = false; _ = Task.Run(async () => { try { await Ready("Manual"); } finally { gate.Release(); } }); - return "Restart accepted."; + return Reply("Restart accepted", "No players are online. The server is restarting.", 0x57F287); } - catch (Exception e) { return $"Denied: {e.Message}"; } + catch (Exception e) { return Reply("Restart unavailable", e.Message, 0xED4245); } finally { if (release) gate.Release(); } } async Task Warn(int seconds) @@ -172,22 +177,31 @@ async Task Schedule(CancellationToken token) } host.AddSlashCommand("status", "Show server status", async (ApplicationCommandContext c) => - !Allowed(c) ? "Not authorised." : await Status()); + !Allowed(c) ? Denied() : await Status()); host.AddSlashCommand("restart", "Restart when no players are online", (ApplicationCommandContext c) => - Allowed(c) ? Manual() : Task.FromResult("Not authorised.")); + Allowed(c) ? Manual() : Task.FromResult(Denied())); host.AddSlashCommand("players", "List online players", async (ApplicationCommandContext c) => - !Allowed(c) ? "Not authorised." : await PlayerList()); + !Allowed(c) ? Denied() : await PlayerList()); host.AddSlashCommandGroup("whitelist", "Manage bot access", group => { - group.AddSubCommand("add", "Add a Discord user", (string discordId, ApplicationCommandContext c) => Whitelist(c, discordId, true)); - group.AddSubCommand("del", "Remove a Discord user", (string discordId, ApplicationCommandContext c) => Whitelist(c, discordId, false)); + group.AddSubCommand("add", "Add a Discord user", (User user, ApplicationCommandContext c) => Whitelist(c, user, true)); + group.AddSubCommand("del", "Remove a Discord user", (User user, ApplicationCommandContext c) => Whitelist(c, user, false)); }); -async Task Status() { try { return $"Server online; {(await Players()).Count} player(s)."; } catch { return "Server unavailable."; } } -async Task PlayerList() +async Task Status() { - try { var p = await Players(); return p.Count == 0 ? "No players online." : $"Online ({p.Count}): {string.Join(", ", p.Names)}"; } - catch { return "Unable to query players."; } + try { return Reply("Server online", $"{(await Players()).Count} player(s) connected.", 0x57F287); } + catch { return Reply("Server unavailable", "Project Zomboid is offline, restarting, or unreachable.", 0xED4245); } +} +async Task PlayerList() +{ + try + { + var p = await Players(); + return Reply("Online players", p.Count == 0 ? "No players are online." : p.Names.Length == 0 + ? $"{p.Count} player(s) online; names unavailable." : string.Join("\n", p.Names.Select(x => $"• {x}")), 0x5865F2); + } + catch { return Reply("Player query failed", "Unable to query the server.", 0xED4245); } } await host.StartAsync();