You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js:实现消息反应与Embed编辑的10秒持续交互

Problem: Discord Urban Dictionary Bot Only Allows One Reaction Switch

I'm building a Discord bot that fetches Urban Dictionary definitions. The intended behavior is that after triggering the command, users can click left/right arrows to cycle through definitions for 10 seconds. Right now, though, it only works for one switch—after that, no more interaction is possible.

Here's my current code:

async execute(message, args) { 
// if (!message.channel.nsfw) return message.channel.send("You can only send messages in a NSFW marked channel.") 
let worder = args[0]; 
if (!worder) return message.channel.send("Specify a word") 
let defin = await ud.all(args.join(' ')).catch(e => { 
message.channel.send("Word not found") 
return; 
}); 
message.channel.send({ embed: generateEmbed(defin, 0) }).then(async message => { 
if (defin.length < 1) return 
await message.react("➡️") 
const filter = (reaction, user) => { 
return ['⬅️', '➡️'].includes(reaction.emoji.name) 
}; 
message.awaitReactions(filter, { time: 1000 }).then(collected => { 
const reaction = collected.first(); 
let currentIndex = 0 
message.reactions.removeAll().then(async() => { 
reaction.emoji.name === '⬅️' ? currentIndex -= 1 : currentIndex += 1 
console.log(currentIndex) 
message.edit(generateEmbed(defin, currentIndex)) 
if (currentIndex !== 0) await message.react('⬅️') 
console.log(currentIndex, defin.length) 
if (currentIndex + 1 < defin.length) await message.react('➡️') 
}) 
}); 
}); 
}

Solution

Got it, let's fix this reaction switching issue. The core problems with your current code are that it only listens for one reaction, resets the index every time, and has a too-short timeout. Here's how to make repeated switches work within the 10-second window:

async execute(message, args) { 
    // if (!message.channel.nsfw) return message.channel.send("You can only send messages in a NSFW marked channel.") 
    let worder = args[0]; 
    if (!worder) return message.channel.send("Specify a word"); 

    let defin = await ud.all(args.join(' ')).catch(e => { 
        message.channel.send("Word not found"); 
        return; 
    }); 

    // Exit early if no definitions exist
    if (!defin || defin.length < 1) return;

    // Send the initial embed with the first definition
    const sentMessage = await message.channel.send({ embed: generateEmbed(defin, 0) });

    // Add initial reaction only if there are multiple definitions
    if (defin.length > 1) {
        await sentMessage.react("➡️");
    }

    let currentIndex = 0;
    const filter = (reaction, user) => { 
        // Only listen to the command sender and valid arrow reactions
        return ['⬅️', '➡️'].includes(reaction.emoji.name) && user.id === message.author.id; 
    }; 

    // Create a collector that listens for reactions for 10 seconds
    const collector = sentMessage.createReactionCollector({ filter, time: 10000 });

    collector.on('collect', async (reaction, user) => {
        // Remove the user's reaction to keep the message clean
        await reaction.users.remove(user);

        // Update index with boundary checks to avoid invalid positions
        if (reaction.emoji.name === '⬅️' && currentIndex > 0) {
            currentIndex--;
        } else if (reaction.emoji.name === '➡️' && currentIndex < defin.length - 1) {
            currentIndex++;
        }

        // Update the embed with the new definition
        await sentMessage.edit({ embed: generateEmbed(defin, currentIndex) });

        // Clear existing reactions before adding new ones
        await sentMessage.reactions.removeAll();

        // Add back appropriate arrows based on current position
        if (currentIndex > 0) {
            await sentMessage.react("⬅️");
        }
        if (currentIndex < defin.length - 1) {
            await sentMessage.react("➡️");
        }
    });

    // Optional: Clean up reactions when the collector times out
    collector.on('end', () => {
        sentMessage.reactions.removeAll().catch(console.error);
    });
}

Key Fixes Explained:

  • Persistent Listener: Switched from awaitReactions to createReactionCollector—this keeps listening for reactions until the 10-second timeout, allowing multiple switches.
  • Retained Index: Moved currentIndex outside the reaction handler so it doesn't reset to 0 every time someone clicks an arrow.
  • User Restriction: Added a check to only respond to the user who triggered the command (prevents random users from messing with the navigation).
  • Boundary Protection: Ensured the index can't go below 0 or above the last definition's position.
  • Reaction Cleanup: Removed the user's reaction after processing, and only show arrows when they're useful (no left arrow on the first definition, no right arrow on the last).
  • Fixed Timeout: Changed time: 1000 to time: 10000 to match your 10-second requirement.

Now users can cycle back and forth through definitions as many times as they want within the 10-second window after running the command.

内容的提问来源于stack exchange,提问作者amrita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:25:31