diff options
| author | Mathias Magnusson <mathias@magnusson.space> | 2025-12-13 02:17:16 +0100 |
|---|---|---|
| committer | Mathias Magnusson <mathias@magnusson.space> | 2025-12-13 02:17:16 +0100 |
| commit | 884d170e8a75db282bee3db04fed60d57139d775 (patch) | |
| tree | 1a59e5ae70dc280e59ba6ede57426f3c4de6ef0b /commands.ts | |
| parent | a744bcd5eb06ce6a7bc39c0ef675d22c29c39ba9 (diff) | |
| download | challe-anka-884d170e8a75db282bee3db04fed60d57139d775.tar.gz | |
move from categories to only forums
Diffstat (limited to 'commands.ts')
| -rw-r--r-- | commands.ts | 149 |
1 files changed, 71 insertions, 78 deletions
diff --git a/commands.ts b/commands.ts index f887cf1..cb3158a 100644 --- a/commands.ts +++ b/commands.ts @@ -2,8 +2,8 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, - CategoryChannel, ChannelType, + ForumChannel, PermissionFlagsBits, SlashCommandBuilder, SlashCommandStringOption, @@ -22,19 +22,25 @@ export let slashCommands = [ .setName("name") .setDescription("Name for the new CTF") .setRequired(true) + ) + .addStringOption( + new SlashCommandStringOption() + .setName("message") + .setDescription("Contents of the initial post in the general thread. Should probably be a link to the CTF platform.") + .setRequired(true) ), handler: newCtf, }, { slashCommand: new SlashCommandBuilder() .setName("archive") - .setDescription("Make this CTF category read-only for everyone"), + .setDescription("Make this CTF forum read-only for everyone"), handler: archiveCtf, }, { slashCommand: new SlashCommandBuilder() .setName("add") - .setDescription("Add a user to this CTF category") + .setDescription("Add a user to this CTF forum") .addUserOption( new SlashCommandUserOption() .setName("user") @@ -46,7 +52,7 @@ export let slashCommands = [ { slashCommand: new SlashCommandBuilder() .setName("remove") - .setDescription("Remove a user from this CTF category") + .setDescription("Remove a user from this CTF forum") .addUserOption( new SlashCommandUserOption() .setName("user") @@ -59,7 +65,7 @@ export let slashCommands = [ export let buttonCommands = { join: { - prefix: "ctf-category:", + prefix: "ctf-forum:", handler: handleJoinCtfButton, }, } as const; @@ -74,11 +80,12 @@ async function newCtf(interaction: ChatInputCommandInteraction) { } let name = interaction.options.getString("name", true); + let link = interaction.options.getString("message", true); await interaction.deferReply({ flags: "Ephemeral" }); - let category = await interaction.guild.channels.create({ + let forum = await interaction.guild.channels.create({ name, - type: ChannelType.GuildCategory, + type: ChannelType.GuildForum, permissionOverwrites: [ { id: interaction.guild.roles.everyone, @@ -87,26 +94,14 @@ async function newCtf(interaction: ChatInputCommandInteraction) { ], }); - await Promise.all([ - await interaction.guild.channels.create({ - name: "info", - type: ChannelType.GuildText, - parent: category.id, - position: 1, - }), - await interaction.guild.channels.create({ - name: "general", - type: ChannelType.GuildText, - parent: category.id, - position: 2, - }), - await interaction.guild.channels.create({ - name: "challs", - type: ChannelType.GuildForum, - parent: category.id, - position: 3, - }), - ]); + let generalThread = await forum.threads.create({ + name: "general", + message: { + content: link, + }, + }); + + await generalThread.pin(); let commandChannel = (interaction.channelId && await interaction.guild.channels.fetch(interaction.channelId)); @@ -117,7 +112,7 @@ async function newCtf(interaction: ChatInputCommandInteraction) { components: [ new ActionRowBuilder<ButtonBuilder>().addComponents( new ButtonBuilder() - .setCustomId(`${buttonCommands.join.prefix}${category.id}`) + .setCustomId(`${buttonCommands.join.prefix}${forum.id}`) .setLabel(`Join ${name}`) .setStyle(ButtonStyle.Primary), ), @@ -125,7 +120,7 @@ async function newCtf(interaction: ChatInputCommandInteraction) { }); await interaction.editReply( - `Created ${category.name}.`, + `Created ${forum.name}.`, ); } @@ -138,13 +133,12 @@ async function archiveCtf(interaction: ChatInputCommandInteraction) { return; } - let category = await getCategory(interaction); + let forum = await getCtfForum(interaction); let everyoneRoleId = interaction.guild.roles.everyone.id; - await category.permissionOverwrites.edit(everyoneRoleId, { + await forum.permissionOverwrites.edit(everyoneRoleId, { ViewChannel: true, - ReadMessageHistory: true, SendMessages: false, SendMessagesInThreads: false, CreatePublicThreads: false, @@ -152,13 +146,13 @@ async function archiveCtf(interaction: ChatInputCommandInteraction) { }); await Promise.all( - category.permissionOverwrites.cache + forum.permissionOverwrites.cache .filter(overwrite => overwrite.id !== everyoneRoleId) - .map(overwrite => category.permissionOverwrites.delete(overwrite.id)) + .map(overwrite => forum.permissionOverwrites.delete(overwrite.id)) ); await interaction.reply({ - content: `Updated ${category.name}: @everyone can read, (mostly) no-one can write.`, + content: `Updated ${forum.name}: @everyone can read, (mostly) no-one can write.`, flags: "Ephemeral", }); } @@ -173,26 +167,28 @@ async function addToCtf(interaction: ChatInputCommandInteraction) { } let user = interaction.options.getUser("user", true); - let category = await getCategory(interaction); + let forum = await getCtfForum(interaction); let member = await interaction.guild.members.fetch(interaction.user.id); - let permissions = category.permissionsFor(member); + let permissions = forum.permissionsFor(member); if (!permissions?.has(PermissionFlagsBits.ManageChannels)) { await interaction.reply({ - content: `You don't have permission to update permissions in ${category.name}.`, + content: `You don't have permission to update permissions in ${forum.name}.`, flags: "Ephemeral", }); return; } - await category.permissionOverwrites.edit(user, { + await forum.permissionOverwrites.edit(user, { ViewChannel: true, + CreatePublicThreads: true, SendMessages: true, + SendMessagesInThreads: true, }); await interaction.reply({ - content: `Granted ${user} access to ${category.name}.`, + content: `Granted ${user} access to ${forum.name}.`, flags: "Ephemeral", }); } @@ -207,28 +203,28 @@ async function removeFromCtf(interaction: ChatInputCommandInteraction) { } let user = interaction.options.getUser("user", true); - let category = await getCategory(interaction); + let forum = await getCtfForum(interaction); let member = await interaction.guild.members.fetch(interaction.user.id); - let permissions = category.permissionsFor(member); + let permissions = forum.permissionsFor(member); if (!permissions?.has(PermissionFlagsBits.ManageChannels)) { await interaction.reply({ - content: `You don't have permission to update permissions in ${category.name}.`, + content: `You don't have permission to update permissions in ${forum.name}.`, flags: "Ephemeral", }); return; } - await category.permissionOverwrites.delete(user.id); + await forum.permissionOverwrites.delete(user.id); await interaction.reply({ - content: `Removed ${user} from ${category.name}.`, + content: `Removed ${user} from ${forum.name}.`, flags: "Ephemeral", }); } -async function handleJoinCtfButton(interaction: ButtonInteraction, categoryId: string) { +async function handleJoinCtfButton(interaction: ButtonInteraction, forumId: string) { if (!interaction.guild) { return await interaction.reply({ content: "This button only works inside a server.", @@ -236,66 +232,63 @@ async function handleJoinCtfButton(interaction: ButtonInteraction, categoryId: s }); } - let categoryChannel = await interaction.guild.channels.fetch(categoryId); + let forumChannel = await interaction.guild.channels.fetch(forumId); - if (!categoryChannel || categoryChannel.type !== ChannelType.GuildCategory) { + if (!forumChannel || forumChannel.type !== ChannelType.GuildForum) { await interaction.reply({ - content: "That category no longer exists.", + content: "That forum no longer exists.", flags: "Ephemeral", }); return; } - await categoryChannel.permissionOverwrites.edit(interaction.user.id, { + if (forumChannel.permissionsFor(interaction.guild.roles.everyone).has(PermissionFlagsBits.ViewChannel)) { + await interaction.reply({ + content: `The CTF has been archived so you can already view it: https://discord.com/channels/${interaction.guild.id}/${forumChannel.id}`, + flags: "Ephemeral", + }); + return; + } + + await forumChannel.permissionOverwrites.edit(interaction.user.id, { ViewChannel: true, + CreatePublicThreads: true, SendMessages: true, + SendMessagesInThreads: true, }); await interaction.reply({ - content: `Granted you access to ${categoryChannel.name}.`, + content: `Granted you access to ${forumChannel.name}.`, flags: "Ephemeral", }); } -async function getCategory(interaction: ButtonInteraction | ChatInputCommandInteraction): Promise<CategoryChannel> { - let errorMsg = "This command can only be used in the `general` or `info` channel of a CTF category."; +async function getCtfForum(interaction: ButtonInteraction | ChatInputCommandInteraction): Promise<ForumChannel> { + let errorMsg = "This command can only be used in a CTF forum channel."; if (!interaction.guild) { await interaction.reply({ content: errorMsg, flags: "Ephemeral" }); throw "done"; } - if (!interaction.channel || interaction.channel.type !== ChannelType.GuildText - || !["general", "info"].includes(interaction.channel.name) - || !interaction.channel.parentId - ) { - await interaction.reply({ content: errorMsg, flags: "Ephemeral" }); - throw "done"; - } + let channel = await interaction.guild.channels.fetch(interaction.channelId); - let category = interaction.channel.parentId && await interaction.guild.channels.fetch(interaction.channel.parentId); - if (!category || category.type !== ChannelType.GuildCategory) { + if (!channel) { await interaction.reply({ content: errorMsg, flags: "Ephemeral" }); throw "done"; } - let allChannels = await interaction.guild.channels.fetch(); - let categoryChildren = [...allChannels.values()].filter((channel) => { - return channel !== null && "parentId" in channel && channel.parentId === category.id; - }); - - let info = categoryChildren.find((channel) => channel?.name === "info"); - let general = categoryChildren.find((channel) => channel?.name === "general"); - let challs = categoryChildren.find((channel) => channel?.name === "challs"); + if (channel.type === ChannelType.GuildForum) { + return channel as ForumChannel; + } - if ( - !info || info.type !== ChannelType.GuildText || - !general || general.type !== ChannelType.GuildText || - !challs || challs.type !== ChannelType.GuildForum - ) { - await interaction.reply({ content: errorMsg, flags: "Ephemeral" }); - throw "done"; + if (channel.isThread() && channel.parentId) { + let parent = await interaction.guild.channels.fetch(channel.parentId); + if (parent && parent.type === ChannelType.GuildForum) { + return parent as ForumChannel; + } } - return category; + await interaction.reply({ content: errorMsg, flags: "Ephemeral" }); + throw "done"; } |
