feat: dashboard

This commit is contained in:
eric
2026-02-26 14:45:57 +01:00
parent 94ad2896cc
commit 3756830ec2
43 changed files with 7043 additions and 2060 deletions

View File

@@ -0,0 +1,173 @@
/**
* Random channels command - control where spontaneous random posts are allowed
*/
import { eq } from "drizzle-orm";
import { ChannelType, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
import type { Command } from "../types";
import { db } from "../../database";
import { botOptions } from "../../database/schema";
function parseChannelIds(raw: string | null | undefined): string[] {
if (!raw) {
return [];
}
try {
const parsed = JSON.parse(raw);
if (!Array.isArray(parsed)) {
return [];
}
return parsed.filter((value): value is string => typeof value === "string");
} catch {
return [];
}
}
async function saveChannelIds(guildId: string, channelIds: string[] | null): Promise<void> {
const now = new Date().toISOString();
await db
.insert(botOptions)
.values({
guild_id: guildId,
spontaneous_channel_ids: channelIds && channelIds.length > 0 ? JSON.stringify(channelIds) : null,
updated_at: now,
})
.onConflictDoUpdate({
target: botOptions.guild_id,
set: {
spontaneous_channel_ids: channelIds && channelIds.length > 0 ? JSON.stringify(channelIds) : null,
updated_at: now,
},
});
}
const command: Command = {
data: new SlashCommandBuilder()
.setName("random-channels")
.setDescription("Control which channels Joel can use for spontaneous random posts")
.setDMPermission(false)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
.addSubcommand((subcommand) =>
subcommand
.setName("add")
.setDescription("Allow random posts in one channel")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("Channel to allow for random posts")
.addChannelTypes(ChannelType.GuildText)
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand
.setName("remove")
.setDescription("Remove one channel from random post allowlist")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("Channel to remove")
.addChannelTypes(ChannelType.GuildText)
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand
.setName("clear")
.setDescription("Clear allowlist so random posts can use any channel")
)
.addSubcommand((subcommand) =>
subcommand
.setName("status")
.setDescription("Show current random post channel settings")
) as SlashCommandBuilder,
category: "moderation",
execute: async (interaction) => {
if (!interaction.inGuild()) {
await interaction.reply({ content: "This command can only be used in a server.", ephemeral: true });
return;
}
const guildId = interaction.guildId;
const subcommand = interaction.options.getSubcommand();
const existing = await db
.select({ spontaneous_channel_ids: botOptions.spontaneous_channel_ids })
.from(botOptions)
.where(eq(botOptions.guild_id, guildId))
.limit(1);
const currentIds = parseChannelIds(existing[0]?.spontaneous_channel_ids);
if (subcommand === "add") {
const channel = interaction.options.getChannel("channel", true);
if (currentIds.includes(channel.id)) {
await interaction.reply({
content: `<#${channel.id}> is already allowed for random posts.`,
ephemeral: true,
});
return;
}
const updatedIds = [...currentIds, channel.id];
await saveChannelIds(guildId, updatedIds);
await interaction.reply({
content: `✅ Added <#${channel.id}> to Joel's random post channels.`,
ephemeral: true,
});
return;
}
if (subcommand === "remove") {
const channel = interaction.options.getChannel("channel", true);
if (!currentIds.includes(channel.id)) {
await interaction.reply({
content: `<#${channel.id}> is not currently in the random post allowlist.`,
ephemeral: true,
});
return;
}
const updatedIds = currentIds.filter((channelId) => channelId !== channel.id);
await saveChannelIds(guildId, updatedIds.length > 0 ? updatedIds : null);
await interaction.reply({
content: `✅ Removed <#${channel.id}> from Joel's random post channels.`,
ephemeral: true,
});
return;
}
if (subcommand === "clear") {
await saveChannelIds(guildId, null);
await interaction.reply({
content: "✅ Random post channel allowlist cleared. Joel can now randomly post in any writable text channel.",
ephemeral: true,
});
return;
}
if (currentIds.length === 0) {
await interaction.reply({
content: "🌐 No random post channel allowlist is set. Joel can randomly post in any writable text channel.",
ephemeral: true,
});
return;
}
const list = currentIds.map((channelId) => `<#${channelId}>`).join(", ");
await interaction.reply({
content: `📍 Joel can randomly post in: ${list}`,
ephemeral: true,
});
},
};
export default command;