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:
- 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.
- Variable Scope Bug: You're using an undefined
messagevariable in themessageReactionAddcallback. Even if you meantreaction.message, that would point to the bot's own message, somessage.authoris the bot itself, not the actual求婚 initiator. - 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




