feat: dashboard
This commit is contained in:
173
src/commands/definitions/random-channels.ts
Normal file
173
src/commands/definitions/random-channels.ts
Normal 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;
|
||||
Reference in New Issue
Block a user