Just some minor improvements to the solution of @LachyLegend for easier use.
TypeScript:
function updateComponent<T extends MessageActionRowComponentBuilder>(interaction: MessageComponentInteraction, newButtonFunc: (component: T) => T, customId = interaction.customId): ActionRowBuilder<MessageActionRowComponentBuilder>[] {
const indices = findComponent(interaction, customId);
if (!indices) {
return [];
}
const actionRows = interaction.message.components.map<ActionRowBuilder<MessageActionRowComponentBuilder>>((row) => ActionRowBuilder.from(row));
newButtonFunc(actionRows[indices.actionRowIndex].components[indices.componentIndex] as T);
return actionRows;
}
function findComponent(interaction: MessageComponentInteraction, customId: string): {actionRowIndex: number, componentIndex: number} | undefined {
const actionRows = interaction.message.components;
for (let actionRowIndex = 0; actionRowIndex < actionRows.length; ++actionRowIndex) {
const actionRow = actionRows[actionRowIndex];
for (let componentIndex = 0; componentIndex < actionRow.components.length; ++componentIndex) {
if (actionRow.components[componentIndex].customId === customId) {
return {
actionRowIndex,
componentIndex,
};
}
}
}
}
JavaScript
function updateComponent(interaction, newButtonFunc, customId = interaction.customId) {
const indices = findComponent(interaction, customId);
if (!indices) {
return [];
}
const actionRows = interaction.message.components.map((row) => ActionRowBuilder.from(row));
newButtonFunc(actionRows[indices.actionRowIndex].components[indices.componentIndex]);
return actionRows;
}
function findComponent(interaction, customId) {
const actionRows = interaction.message.components;
for (let actionRowIndex = 0; actionRowIndex < actionRows.length; ++actionRowIndex) {
const actionRow = actionRows[actionRowIndex];
for (let componentIndex = 0; componentIndex < actionRow.components.length; ++componentIndex) {
if (actionRow.components[componentIndex].customId === customId) {
return {
actionRowIndex,
componentIndex,
};
}
}
}
}
usage:
const reply = await interaction.reply(messageContent);
const collector = reply.createMessageComponentCollector({ componentType: ComponentType.Button, time: 3_600_000 });
collector.on('collect', async (buttonInteraction) => {
const newActionRows = updateComponent(buttonInteraction, (button) => button.setStyle(button.data.style === ButtonStyle.Success ? ButtonStyle.Danger : ButtonStyle.Success));
// updateButton<ButtonBuilder>(...) or updateButton<TheBuilderYouOverride>(...) for TypeScript
await reply.edit({
content: buttonInteraction.message.content,
components: newActionRows,
});
buttonInteraction.update({});
});