diff --git a/backend/src/plugins/RoleButtons/events/buttonInteraction.ts b/backend/src/plugins/RoleButtons/events/buttonInteraction.ts index 9384d5a2..1eeb8f91 100644 --- a/backend/src/plugins/RoleButtons/events/buttonInteraction.ts +++ b/backend/src/plugins/RoleButtons/events/buttonInteraction.ts @@ -3,16 +3,22 @@ import { RoleButtonsPluginType, TRoleButtonOption } from "../types"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; import { GuildMember } from "discord.js"; import { getAllRolesInButtons } from "../functions/getAllRolesInButtons"; +import { parseCustomId } from "../../../utils/parseCustomId"; export const onButtonInteraction = typedGuildEventListener()({ event: "interactionCreate", async listener({ pluginData, args }) { - if (!args.interaction.isButton() || !args.interaction.customId.startsWith("roleButtons:")) { + if (!args.interaction.isButton()) { + return; + } + + const { namespace, data } = parseCustomId(args.interaction.customId); + if (namespace !== "roleButtons") { return; } const config = pluginData.config.get(); - const [, name, optionIndex] = args.interaction.customId.split(":"); + const { name, index: optionIndex } = data; // For some reason TS's type inference fails here so using a type annotation const buttons = config.buttons[name]; const option: TRoleButtonOption | undefined = buttons?.options[optionIndex]; diff --git a/backend/src/plugins/RoleButtons/functions/applyRoleButtons.ts b/backend/src/plugins/RoleButtons/functions/applyRoleButtons.ts index 30b413ef..18c8beb5 100644 --- a/backend/src/plugins/RoleButtons/functions/applyRoleButtons.ts +++ b/backend/src/plugins/RoleButtons/functions/applyRoleButtons.ts @@ -5,6 +5,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin"; import { Message, MessageButton, MessageEditOptions, MessageOptions, Snowflake } from "discord.js"; import { RoleButtonsItem } from "../../../data/entities/RoleButtonsItem"; import { splitButtonsIntoRows } from "./splitButtonsIntoRows"; +import { buildCustomId } from "../../../utils/buildCustomId"; const channelMessageRegex = new RegExp(`^(${snowflakeRegex.source})-(${snowflakeRegex.source})$`); @@ -107,7 +108,7 @@ export async function applyRoleButtons( const button = new MessageButton() .setLabel(opt.label ?? "") .setStyle(opt.style ?? "PRIMARY") - .setCustomId(`roleButtons:${configItem.name}:${index}:${Math.round(Date.now() / 1000)}`); + .setCustomId(buildCustomId("roleButtons", { name: configItem.name, index })); if (opt.emoji) { const emo = pluginData.client.emojis.resolve(opt.emoji as Snowflake) ?? opt.emoji; diff --git a/backend/src/utils/buildCustomId.ts b/backend/src/utils/buildCustomId.ts new file mode 100644 index 00000000..3930d112 --- /dev/null +++ b/backend/src/utils/buildCustomId.ts @@ -0,0 +1,3 @@ +export function buildCustomId(namespace: string, data: any = {}) { + return `${namespace}:${Date.now()}:${JSON.stringify(data)}`; +} diff --git a/backend/src/utils/parseCustomId.ts b/backend/src/utils/parseCustomId.ts new file mode 100644 index 00000000..2d95a3a1 --- /dev/null +++ b/backend/src/utils/parseCustomId.ts @@ -0,0 +1,17 @@ +const customIdFormat = /^([^:]+):\d+:(.*)$/; + +export function parseCustomId(customId: string): { namespace: string; data: any } { + const parts = customId.match(customIdFormat); + if (!parts) { + return { + namespace: "", + data: null, + }; + } + + return { + namespace: parts[1], + // Skipping timestamp + data: JSON.parse(parts[2]), + }; +}