summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands.ts149
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";
}