You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Discord机器人婚姻系统重复发送结婚通知Embed消息Bug修复咨询

Fixing Duplicate Marriage Notification Embeds in Discord Bot

Hey there, let's break down why you're seeing duplicate marriage notifications and fix it step by step.

What's Causing the Duplicates?

Your current code has three critical issues leading to repeated embeds:

  1. No Targeted Message Filtering: You're listening for all ✅ reactions across every message in your server—including old, already-resolved求婚 messages from previous marriages/divorces.
  2. Variable Scope Bug: You're using an undefined message variable in the messageReactionAdd callback. Even if you meant reaction.message, that would point to the bot's own message, so message.author is the bot itself, not the actual求婚 initiator.
  3. No Duplicate Prevention: There's nothing stopping the same求婚 message from being processed multiple times if someone clicks the reaction again.

Fixed Code Implementation

First, we need to update your marry command to tag求婚 messages with identifiable data, then fix the reaction listener to only interact with those specific messages.

Step 1: Update the marry Command to Tag求婚 Messages

When sending the initial求婚 prompt, embed the IDs of the求婚 initiator and target so we can reference them later:

// Add this to your existing messageCreate command handler
client.on('messageCreate', async (message) => {
  if (message.content.startsWith('!marry')) {
    const targetUser = message.mentions.users.first();
    if (!targetUser) return message.reply("Please mention the user you want to marry!");
    
    // Create a proposal embed with embedded user IDs
    const proposalEmbed = new Discord.MessageEmbed()
      .setTitle("💍 Marriage Proposal")
      .setDescription(`${message.author} has proposed to ${targetUser}! Click ✅ to accept or ❌ to decline.`)
      .addField("Initiator ID", message.author.id, true)
      .addField("Target ID", targetUser.id, true);
    
    const proposalMsg = await message.channel.send({ embeds: [proposalEmbed] });
    await proposalMsg.react('✅');
    await proposalMsg.react('❌');
  }
});

Step 2: Fix the messageReactionAdd Listener

Now, modify the reaction handler to only process valid求婚 messages, prevent duplicates, and use the correct user data:

client.on('messageReactionAdd', async (reaction, user) => {
  // Handle partial messages/reactions
  if (reaction.message.partial) await reaction.message.fetch();
  if (reaction.partial) await reaction.fetch();
  
  // Ignore bots and DM messages
  if (user.bot || !reaction.message.guild) return;

  // 1. Verify this is a valid求婚 message
  const embed = reaction.message.embeds[0];
  if (!embed || !embed.fields.find(f => f.name === "Initiator ID") || !embed.fields.find(f => f.name === "Target ID")) {
    return; // Exit if this isn't a tagged求婚 message
  }

  // Extract user IDs from the embed
  const initiatorId = embed.fields.find(f => f.name === "Initiator ID").value;
  const targetId = embed.fields.find(f => f.name === "Target ID").value;

  // 2. Only let the targeted user interact with the reaction
  if (user.id !== targetId) {
    await reaction.users.remove(user); // Remove unauthorized reactions
    return;
  }

  // 3. Handle Acceptance (✅)
  if (reaction.emoji.name === '✅') {
    // Remove all reactions to prevent duplicate processing
    await reaction.message.reactions.removeAll();

    const guild = reaction.message.guild;
    const initiator = await guild.members.fetch(initiatorId);
    const target = await guild.members.fetch(targetId);

    // Update roles
    await initiator.roles.add(marriedRole);
    await initiator.roles.remove(singleRole);
    await target.roles.add(marriedRole);
    await target.roles.remove(singleRole);

    // Send single marriage notification
    const marriedEmbed = new Discord.MessageEmbed()
      .setDescription(`**${target.user}** & **${initiator.user}** are now married! 🎉`)
      .setImage('https://64.media.tumblr.com/604a79e043662b7dc556919c502718df/tumblr_p0dsd3yYos1uxvvvzo1_500.gifv');
    await reaction.message.channel.send({ embeds: [marriedEmbed] });

    // Update database (use updateOne instead of replaceOne to avoid overwriting full documents)
    await profileModel.updateOne(
      { userID: initiatorId },
      { $set: { spouse: targetId } }
    );
    await profileModel.updateOne(
      { userID: targetId },
      { $set: { spouse: initiatorId } }
    );
  }

  // 4. Handle Rejection (❌)
  if (reaction.emoji.name === '❌') {
    // Remove all reactions to prevent duplicate processing
    await reaction.message.reactions.removeAll();

    const initiator = await reaction.message.guild.members.fetch(initiatorId);
    const rejectEmbed = new Discord.MessageEmbed()
      .setDescription(`Sorry **${initiator.user}**, ${user} does not want to marry you.`);
    await reaction.message.channel.send({ embeds: [rejectEmbed] });
  }
});

Key Fixes Explained

  • Targeted Message Filtering: We check for the custom "Initiator ID" and "Target ID" fields in the embed to ensure we only process valid求婚 messages.
  • Duplicate Prevention: After processing a reaction, we remove all reactions from the message so it can't be triggered again.
  • Correct User Data: We pull the actual求婚 initiator and target IDs from the embed, fixing the earlier bug where you were referencing the bot as the message author.
  • Role Security: We only let the targeted user interact with the reaction, preventing other server members from messing with求婚 requests.

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

火山引擎 最新活动