Use embedded slash command responses
This commit is contained in:
+36
-22
@@ -9,6 +9,7 @@ using NetCord;
|
|||||||
using NetCord.Gateway;
|
using NetCord.Gateway;
|
||||||
using NetCord.Hosting.Gateway;
|
using NetCord.Hosting.Gateway;
|
||||||
using NetCord.Hosting.Services.ApplicationCommands;
|
using NetCord.Hosting.Services.ApplicationCommands;
|
||||||
|
using NetCord.Rest;
|
||||||
using NetCord.Services.ApplicationCommands;
|
using NetCord.Services.ApplicationCommands;
|
||||||
|
|
||||||
string Env(string key, string? fallback = null) => Environment.GetEnvironmentVariable(key) ?? fallback
|
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();
|
.AddApplicationCommands();
|
||||||
var host = builder.Build();
|
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); }
|
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 (c.User.Id != initialUser) return Denied("Only the whitelist owner can manage access.");
|
||||||
if (!ulong.TryParse(discordId, out ulong id)) return "Invalid Discord ID.";
|
if (!add && user.Id == initialUser) return Reply("Whitelist unchanged", "The whitelist owner cannot be removed.", 0xFEE75C);
|
||||||
if (!add && id == initialUser) return "The whitelist owner cannot be removed.";
|
|
||||||
lock (whitelistLock)
|
lock (whitelistLock)
|
||||||
{
|
{
|
||||||
bool changed = add ? whitelist.Add(id) : whitelist.Remove(id);
|
bool changed = add ? whitelist.Add(user.Id) : whitelist.Remove(user.Id);
|
||||||
if (!changed) return add ? "Already whitelisted." : "Not whitelisted.";
|
if (!changed) return Reply("Whitelist unchanged", add ? $"<@{user.Id}> is already whitelisted." : $"<@{user.Id}> is not whitelisted.", 0xFEE75C);
|
||||||
string temp = whitelistPath + ".tmp";
|
string temp = whitelistPath + ".tmp";
|
||||||
File.WriteAllLines(temp, whitelist.Order().Select(x => x.ToString()));
|
File.WriteAllLines(temp, whitelist.Order().Select(x => x.ToString()));
|
||||||
File.Move(temp, whitelistPath, true);
|
File.Move(temp, whitelistPath, true);
|
||||||
return $"{(add ? "Added" : "Removed")} <@{id}>.";
|
return Reply("Whitelist updated", $"{(add ? "Added" : "Removed")} <@{user.Id}>.", 0x57F287);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async Task<string> Command(string command, bool allowDisconnect = false)
|
async Task<string> 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.");
|
Console.Error.WriteLine($"{kind} restart timed out waiting for readiness.");
|
||||||
}
|
}
|
||||||
async Task<string> Manual()
|
async Task<InteractionMessageProperties> 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;
|
bool release = true;
|
||||||
try
|
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;
|
int count = (await Players()).Count;
|
||||||
if (count == 0) 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();
|
await Quit();
|
||||||
lastManual = DateTimeOffset.UtcNow;
|
lastManual = DateTimeOffset.UtcNow;
|
||||||
release = false;
|
release = false;
|
||||||
_ = Task.Run(async () => { try { await Ready("Manual"); } finally { gate.Release(); } });
|
_ = 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(); }
|
finally { if (release) gate.Release(); }
|
||||||
}
|
}
|
||||||
async Task Warn(int seconds)
|
async Task Warn(int seconds)
|
||||||
@@ -172,22 +177,31 @@ async Task Schedule(CancellationToken token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
host.AddSlashCommand("status", "Show server status", async (ApplicationCommandContext c) =>
|
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) =>
|
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) =>
|
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 =>
|
host.AddSlashCommandGroup("whitelist", "Manage bot access", group =>
|
||||||
{
|
{
|
||||||
group.AddSubCommand("add", "Add a Discord user", (string discordId, ApplicationCommandContext c) => Whitelist(c, discordId, true));
|
group.AddSubCommand("add", "Add a Discord user", (User user, ApplicationCommandContext c) => Whitelist(c, user, true));
|
||||||
group.AddSubCommand("del", "Remove a Discord user", (string discordId, ApplicationCommandContext c) => Whitelist(c, discordId, false));
|
group.AddSubCommand("del", "Remove a Discord user", (User user, ApplicationCommandContext c) => Whitelist(c, user, false));
|
||||||
});
|
});
|
||||||
|
|
||||||
async Task<string> Status() { try { return $"Server online; {(await Players()).Count} player(s)."; } catch { return "Server unavailable."; } }
|
async Task<InteractionMessageProperties> Status()
|
||||||
async Task<string> PlayerList()
|
|
||||||
{
|
{
|
||||||
try { var p = await Players(); return p.Count == 0 ? "No players online." : $"Online ({p.Count}): {string.Join(", ", p.Names)}"; }
|
try { return Reply("Server online", $"{(await Players()).Count} player(s) connected.", 0x57F287); }
|
||||||
catch { return "Unable to query players."; }
|
catch { return Reply("Server unavailable", "Project Zomboid is offline, restarting, or unreachable.", 0xED4245); }
|
||||||
|
}
|
||||||
|
async Task<InteractionMessageProperties> 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();
|
await host.StartAsync();
|
||||||
|
|||||||
Reference in New Issue
Block a user