From 5b77f7eebf02bfa7003286305716aa4ecdeda3a5 Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Wed, 7 Feb 2024 13:37:27 +0200 Subject: [PATCH 1/7] Initial commit - Focus mode This starts the work in setting up a focus mode interaction in Valkyrie. --- discord-scripts/focus-mode.ts | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 discord-scripts/focus-mode.ts diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts new file mode 100644 index 00000000..d9a208ec --- /dev/null +++ b/discord-scripts/focus-mode.ts @@ -0,0 +1,66 @@ +import { + ChannelType, + Client, + ButtonStyle, + ButtonBuilder, + ActionRowBuilder, + TextChannel, +} from "discord.js" +import { Robot } from "hubot" + +export default async function setupFocusChannels( + discordClient: Client, + robot: Robot, +) { + discordClient.on("ready", async () => { + discordClient.guilds.cache.forEach(async (guild) => { + const focusChannel = guild.channels.cache.find( + (channel) => + channel.type === ChannelType.GuildText && + channel.name.startsWith("focus"), + ) as TextChannel | undefined + + if (!focusChannel) { + robot.logger.info(`Focus channel not found in guild: ${guild.name}`) + return + } + + const actionRow = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("enable-focus") + .setLabel("Enable Focus") + .setStyle(ButtonStyle.Success), + new ButtonBuilder() + .setCustomId("disable-focus") + .setLabel("Disable Focus") + .setStyle(ButtonStyle.Danger), + ) + + await focusChannel.send({ + content: + "**Focus Mode**\nSelect an option to enable or disable focus mode.", + components: [actionRow], + }) + + robot.logger.info( + `Focus mode options sent to the focus channel in guild: ${guild.name}`, + ) + }) + }) + + discordClient.on("interactionCreate", async (interaction) => { + if (interaction.isButton()) { + if (interaction.customId === "enable-focus") { + await interaction.reply({ + content: "Focus mode enabled.", + ephemeral: true, + }) + } else if (interaction.customId === "disable-focus") { + await interaction.reply({ + content: "Focus mode disabled.", + ephemeral: true, + }) + } + } + }) +} From a5192a2598c9b4be737d6760e6dafef335f6cdab Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Thu, 8 Feb 2024 12:37:23 +0200 Subject: [PATCH 2/7] Set button states This sets correct button states whether focus mode is enabled / disabled. --- discord-scripts/focus-mode.ts | 110 ++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 32 deletions(-) diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index d9a208ec..2da876ac 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -5,15 +5,23 @@ import { ButtonBuilder, ActionRowBuilder, TextChannel, + Interaction, + Message, } from "discord.js" import { Robot } from "hubot" +const focusModeState: Map = new Map() + export default async function setupFocusChannels( discordClient: Client, robot: Robot, ) { discordClient.on("ready", async () => { + robot.logger.info("Focus mode script loaded!") discordClient.guilds.cache.forEach(async (guild) => { + // initialize for each guild + focusModeState.set(guild.id, false) + const focusChannel = guild.channels.cache.find( (channel) => channel.type === ChannelType.GuildText && @@ -25,42 +33,80 @@ export default async function setupFocusChannels( return } - const actionRow = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setCustomId("enable-focus") - .setLabel("Enable Focus") - .setStyle(ButtonStyle.Success), - new ButtonBuilder() - .setCustomId("disable-focus") - .setLabel("Disable Focus") - .setStyle(ButtonStyle.Danger), - ) - - await focusChannel.send({ - content: - "**Focus Mode**\nSelect an option to enable or disable focus mode.", - components: [actionRow], - }) - - robot.logger.info( - `Focus mode options sent to the focus channel in guild: ${guild.name}`, - ) + sendFocusModeMessage(focusChannel, guild.id, robot) }) }) discordClient.on("interactionCreate", async (interaction) => { - if (interaction.isButton()) { - if (interaction.customId === "enable-focus") { - await interaction.reply({ - content: "Focus mode enabled.", - ephemeral: true, - }) - } else if (interaction.customId === "disable-focus") { - await interaction.reply({ - content: "Focus mode disabled.", - ephemeral: true, - }) - } + if (!interaction.isButton()) return + + const guildId = interaction.guildId + if (!guildId) return + + let isEnabled = focusModeState.get(guildId) || false + + if (interaction.customId === "enable-focus") { + isEnabled = true + await interaction.reply({ + content: "Focus mode enabled.", + ephemeral: true, + }) + } else if (interaction.customId === "disable-focus") { + isEnabled = false + await interaction.reply({ + content: "Focus mode disabled.", + ephemeral: true, + }) + } + + focusModeState.set(guildId, isEnabled) + + // update original message if possible, or send a new one + if (interaction.message instanceof Message) { + sendFocusModeMessage( + interaction.channel as TextChannel, + guildId, + robot, + interaction.message, + ) } }) } + +async function sendFocusModeMessage( + focusChannel: TextChannel, + guildId: string, + robot: Robot, + originalMessage?: Message, +) { + const isEnabled = focusModeState.get(guildId) || false + + const actionRow = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("enable-focus") + .setLabel("Enable Focus") + .setStyle(ButtonStyle.Success) + .setDisabled(isEnabled), + new ButtonBuilder() + .setCustomId("disable-focus") + .setLabel("Disable Focus") + .setStyle(ButtonStyle.Danger) + .setDisabled(!isEnabled), + ) + + const messageContent = { + content: + "**Focus Mode**\nSelect an option to enable or disable focus mode.", + components: [actionRow], + } + + if (originalMessage) { + await originalMessage.edit(messageContent) + } else { + await focusChannel.send(messageContent) + } + + robot.logger.info( + `Focus mode options updated in the focus channel of guild: ${guildId}`, + ) +} From 1cb99f774a096ba762efee2f2ced4b7b3d700e5b Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Thu, 8 Feb 2024 13:01:45 +0200 Subject: [PATCH 3/7] Rewrite fules WIP - Just changing message events for testing on test-valkyrie instance. --- discord-scripts/focus-mode.ts | 39 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index 2da876ac..883a2114 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -16,25 +16,30 @@ export default async function setupFocusChannels( discordClient: Client, robot: Robot, ) { - discordClient.on("ready", async () => { - robot.logger.info("Focus mode script loaded!") - discordClient.guilds.cache.forEach(async (guild) => { - // initialize for each guild - focusModeState.set(guild.id, false) - - const focusChannel = guild.channels.cache.find( - (channel) => - channel.type === ChannelType.GuildText && - channel.name.startsWith("focus"), - ) as TextChannel | undefined - - if (!focusChannel) { - robot.logger.info(`Focus channel not found in guild: ${guild.name}`) - return + discordClient.on("messageCreate", async (message) => { + if (message.author.bot) return + + if ( + message.guild && + message.channel.type === ChannelType.GuildText && + message.channel.name.startsWith("focus") + ) { + const guildId = message.guild.id + const focusChannel = message.channel as TextChannel + + if (!focusModeState.has(guildId)) { + focusModeState.set(guildId, false) + robot.logger.info( + `Initializing focus mode state for guild: ${message.guild.name}`, + ) } - sendFocusModeMessage(focusChannel, guild.id, robot) - }) + robot.logger.info( + `Message received in focus channel of guild: ${message.guild.name}`, + ) + + await sendFocusModeMessage(focusChannel, guildId, robot) + } }) discordClient.on("interactionCreate", async (interaction) => { From c3b7a99a8c9c51f4c1721ece444c11208e2dddde Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Thu, 8 Feb 2024 13:12:52 +0200 Subject: [PATCH 4/7] Linter fixes - Resolve issues from lint --- discord-scripts/focus-mode.ts | 77 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index 883a2114..a7688b1c 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -5,13 +5,50 @@ import { ButtonBuilder, ActionRowBuilder, TextChannel, - Interaction, Message, } from "discord.js" import { Robot } from "hubot" const focusModeState: Map = new Map() +async function sendFocusModeMessage( + focusChannel: TextChannel, + guildId: string, + robot: Robot, + originalMessage?: Message, +) { + const isEnabled = focusModeState.get(guildId) || false + + const actionRow = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("enable-focus") + .setLabel("Enable Focus") + .setStyle(ButtonStyle.Success) + .setDisabled(isEnabled), + new ButtonBuilder() + .setCustomId("disable-focus") + .setLabel("Disable Focus") + .setStyle(ButtonStyle.Danger) + .setDisabled(!isEnabled), + ) + + const messageContent = { + content: + "**Focus Mode**\nSelect an option to enable or disable focus mode.", + components: [actionRow], + } + + if (originalMessage) { + await originalMessage.edit(messageContent) + } else { + await focusChannel.send(messageContent) + } + + robot.logger.info( + `Focus mode options updated in the focus channel of guild: ${guildId}`, + ) +} + export default async function setupFocusChannels( discordClient: Client, robot: Robot, @@ -77,41 +114,3 @@ export default async function setupFocusChannels( } }) } - -async function sendFocusModeMessage( - focusChannel: TextChannel, - guildId: string, - robot: Robot, - originalMessage?: Message, -) { - const isEnabled = focusModeState.get(guildId) || false - - const actionRow = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setCustomId("enable-focus") - .setLabel("Enable Focus") - .setStyle(ButtonStyle.Success) - .setDisabled(isEnabled), - new ButtonBuilder() - .setCustomId("disable-focus") - .setLabel("Disable Focus") - .setStyle(ButtonStyle.Danger) - .setDisabled(!isEnabled), - ) - - const messageContent = { - content: - "**Focus Mode**\nSelect an option to enable or disable focus mode.", - components: [actionRow], - } - - if (originalMessage) { - await originalMessage.edit(messageContent) - } else { - await focusChannel.send(messageContent) - } - - robot.logger.info( - `Focus mode options updated in the focus channel of guild: ${guildId}`, - ) -} From f3441996807e03d1ffb3c236442d92d794a677de Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Thu, 8 Feb 2024 14:24:09 +0200 Subject: [PATCH 5/7] Add role manager This commit adds a basic role manager linked to test-valkyrie instance for now, to easily assign focus roles on and off based on button interactions. --- discord-scripts/focus-mode.ts | 19 +++++++++-- .../role-management/role-management.ts | 34 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 discord-scripts/role-management/role-management.ts diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index a7688b1c..47ffad87 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -8,6 +8,7 @@ import { Message, } from "discord.js" import { Robot } from "hubot" +import manageRole from "./role-management/role-management.ts" const focusModeState: Map = new Map() @@ -83,7 +84,7 @@ export default async function setupFocusChannels( if (!interaction.isButton()) return const guildId = interaction.guildId - if (!guildId) return + if (!guildId || !interaction.member) return let isEnabled = focusModeState.get(guildId) || false @@ -93,17 +94,29 @@ export default async function setupFocusChannels( content: "Focus mode enabled.", ephemeral: true, }) + await manageRole( + discordClient, + guildId, + interaction.member.user.id, + "1205116222161813545", + "add", + ) } else if (interaction.customId === "disable-focus") { isEnabled = false await interaction.reply({ content: "Focus mode disabled.", ephemeral: true, }) + await manageRole( + discordClient, + guildId, + interaction.member.user.id, + "1205116222161813545", + "remove", + ) } focusModeState.set(guildId, isEnabled) - - // update original message if possible, or send a new one if (interaction.message instanceof Message) { sendFocusModeMessage( interaction.channel as TextChannel, diff --git a/discord-scripts/role-management/role-management.ts b/discord-scripts/role-management/role-management.ts new file mode 100644 index 00000000..18ab9f6a --- /dev/null +++ b/discord-scripts/role-management/role-management.ts @@ -0,0 +1,34 @@ +import { Client } from "discord.js" + +export default async function manageRole( + discordClient: Client, + guildId: string, + memberId: string, + roleId: string, + action: "add" | "remove", +): Promise { + if (!discordClient) { + throw new Error("Discord client is not initialized.") + } + + const guild = await discordClient.guilds.fetch(guildId) + if (!guild) throw new Error("Guild not found.") + + const member = await guild.members.fetch(memberId) + if (!member) throw new Error("Member not found.") + + const role = await guild.roles.fetch(roleId) + if (!role) throw new Error("Role not found.") + + if (action === "add") { + if (member.roles.cache.has(roleId)) { + return + } + await member.roles.add(role) + } else if (action === "remove") { + if (!member.roles.cache.has(roleId)) { + return + } + await member.roles.remove(role) + } +} From 1ff4e2611c52cfc05d97e3d1402ee197a37c4a09 Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Fri, 9 Feb 2024 10:32:17 +0200 Subject: [PATCH 6/7] Naming conventions Change `role-management.ts` to `index.ts` --- discord-scripts/focus-mode.ts | 2 +- .../role-management/{role-management.ts => index.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename discord-scripts/role-management/{role-management.ts => index.ts} (100%) diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index 47ffad87..035dbe96 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -8,7 +8,7 @@ import { Message, } from "discord.js" import { Robot } from "hubot" -import manageRole from "./role-management/role-management.ts" +import manageRole from "./role-management/index.ts" const focusModeState: Map = new Map() diff --git a/discord-scripts/role-management/role-management.ts b/discord-scripts/role-management/index.ts similarity index 100% rename from discord-scripts/role-management/role-management.ts rename to discord-scripts/role-management/index.ts From 66611ac62c5b2cee6495685645a9b9087254f08a Mon Sep 17 00:00:00 2001 From: Erik Zuuring Date: Wed, 14 Feb 2024 12:29:44 +0200 Subject: [PATCH 7/7] Refactor code This commit fixes the issue on runtime, so now the focusmode message is sent as soon as the `discordClient` can confirm there is a channel named `verify`. --- discord-scripts/focus-mode.ts | 49 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/discord-scripts/focus-mode.ts b/discord-scripts/focus-mode.ts index 035dbe96..ef391378 100644 --- a/discord-scripts/focus-mode.ts +++ b/discord-scripts/focus-mode.ts @@ -54,31 +54,36 @@ export default async function setupFocusChannels( discordClient: Client, robot: Robot, ) { - discordClient.on("messageCreate", async (message) => { - if (message.author.bot) return - - if ( - message.guild && - message.channel.type === ChannelType.GuildText && - message.channel.name.startsWith("focus") - ) { - const guildId = message.guild.id - const focusChannel = message.channel as TextChannel - - if (!focusModeState.has(guildId)) { - focusModeState.set(guildId, false) - robot.logger.info( - `Initializing focus mode state for guild: ${message.guild.name}`, - ) - } + const { application } = discordClient + + if (application) { + robot.logger.info("Discord client ready, setting up focus channels.") - robot.logger.info( - `Message received in focus channel of guild: ${message.guild.name}`, + discordClient.guilds.cache.forEach(async (guild) => { + const focusChannels = guild.channels.cache.filter( + (channel) => + channel.type === ChannelType.GuildText && + channel.name.startsWith("focus"), ) - await sendFocusModeMessage(focusChannel, guildId, robot) - } - }) + focusChannels.forEach(async (channel) => { + const focusChannel = channel as TextChannel + const guildId = guild.id + + if (!focusModeState.has(guildId)) { + focusModeState.set(guildId, false) + robot.logger.info( + `Initializing focus mode state for guild: ${guild.name}`, + ) + } + + robot.logger.info( + `Setting up focus mode for channel: ${channel.name} in guild: ${guild.name}`, + ) + await sendFocusModeMessage(focusChannel, guildId, robot) + }) + }) + } discordClient.on("interactionCreate", async (interaction) => { if (!interaction.isButton()) return