如何修复Discord.js中AFK命令跨服务器触发解除的问题
The root of your problem is that you're storing AFK status using only the user's ID as part of the database key—this makes the AFK state global across all servers. When you set AFK in one server, the bot checks for that user's ID everywhere, so sending a message in any other server will trigger the "welcome back" message and clear the AFK status entirely.
To fix this, you need to tie the AFK state to both the user ID and the server (guild) ID in your database keys. This way, each server's AFK status is independent of the others.
Step-by-Step Fixes
- Modify database keys to include guild ID: Replace keys like
message.author.id + '.afk'with${message.author.id}-${message.guild.id}.afk(and similar for the AFK message key). This creates a unique entry per user per server. - Update all message event handlers: Adjust each part of your code to check and modify the server-specific AFK entries instead of global ones.
- Optional: Combine event handlers: Merging separate
messageevents into one reduces redundant checks and makes maintenance easier.
Revised Code
bot.afk = new Map(); // Combined message handler for cleaner, more efficient logic bot.on("message", message => { // Ignore messages from bots if (message.author.bot) return; // Define server-specific keys for AFK tracking const afkKey = `${message.author.id}-${message.guild.id}.afk`; const afkMessageKey = `${message.author.id}-${message.guild.id}.messageafk`; // Check if the sender is AFK IN THIS SERVER if (db.has(afkKey)) { message.channel.send("welcome back!"); db.delete(afkKey); db.delete(afkMessageKey); } // Check if mentioned users are AFK IN THIS SERVER message.mentions.users.forEach(user => { const mentionedAfkKey = `${user.id}-${message.guild.id}.afk`; if (db.has(mentionedAfkKey)) { // Pull and display their custom AFK message if available const afkReason = db.get(afkMessageKey) || "No reason provided"; message.channel.send(`That user is AFK! Reason: ${afkReason}`); } }); // Handle AFK command const PREFIX = "!"; // Ensure this matches your actual prefix if (!message.content.startsWith(PREFIX)) return; const args = message.content.substring(PREFIX.length).split(' '); switch (args[0]) { case 'afk': db.set(afkKey, 'true'); // Store AFK reason as a string instead of array for readability db.set(afkMessageKey, args.slice(1).join(' ') || "AFK"); message.channel.send(`You are now AFK`); break; }; });
Key Changes Explained
- Server-specific tracking: Using
${user.id}-${guild.id}ensures AFK status is isolated to the server where it was set. Sending a message in another server won't interfere with it. - Cleaner AFK messages: Joined the command arguments into a single string instead of storing an array, so the reason displays properly when mentioned.
- Reduced redundancy: Combining all message-related logic into one event handler cuts down on unnecessary event triggers and makes the code easier to debug.
Now, when you set AFK in Server A, only sending a message in Server A will clear your AFK status there—your AFK state in other servers remains untouched.
内容的提问来源于stack exchange,提问作者Wide

