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

Discord.js:实现支持提及用户/账号ID的封禁命令并解决非服务器成员权限检查报错

Fixing the Ban Command: Handling User IDs and Permission Checks Correctly

Let's break down what's going wrong and fix your ban command step by step.

The Root Cause of Your Error

The guild.members.fetch(args[0]) method returns a Promise, not a direct GuildMember object. When you try to call target.hasPermission() on a Promise, you get that TypeError because Promises don't have that method. Additionally, your permission check logic runs regardless of whether you're using a mention or an ID, which doesn't align with your requirement to only check permissions when mentioning a user.

Step-by-Step Fixes

Here's the revised code with key improvements explained:

const Discord = require('discord.js')
module.exports = {
 name: "ban",
 description: "ban someone",
 execute: async(client, message, args) => {
  // Check if the user has permission to ban
  if(!message.member.hasPermission("BAN_MEMBERS")) {
    return message.reply("you don't have enough permissions to use this command.").then(m => m.delete({ timeout: 5000 }));
  }

  const guild = message.guild;
  let target;
  const mentionedMember = message.mentions.members.first();

  // First try to get the mentioned member
  if (mentionedMember) {
    target = mentionedMember;
  } else if (args[0]) {
    // Fetch member by ID (resolve the Promise with await)
    try {
      target = await guild.members.fetch(args[0]);
    } catch (err) {
      // Handle invalid ID or user not in server
      return message.reply("Could not find a user with that ID.").then(m => m.delete({ timeout: 5000 }));
    }
  }

  if(!target) {
    return message.reply("please mention someone or provide a valid user ID to ban.").then(m => m.delete({ timeout: 5000 }));
  }

  // Only check permissions if the user was mentioned (your requirement)
  if (mentionedMember) {
    if(target.hasPermission("MANAGE_MESSAGES")) {
      return message.reply("you cannot ban a staff member.").then(m => m.delete({ timeout: 5000 }));
    }
  }

  // Prevent self-ban and bot-ban
  if(target.id === message.author.id) {
    return message.reply("you cannot ban yourself.").then(m => m.delete({ timeout: 5000 }));
  }
  if(target.id === client.user.id) {
    return message.reply("you cannot ban the bot.").then(m => m.delete({ timeout: 5000 }));
  }

  // Handle ban reason
  let reason = args.slice(1).join(' ');
  if(!reason) reason = "No reason given.";

  // Send DM to banned user (handle cases where DMs are disabled)
  const dmembed = new Discord.MessageEmbed()
   .setTitle("You have been banned from Rice Farm #11")
   .addField("Moderator", message.author)
   .addField("Reason", `${reason}`)
   .setColor("RED")
   .setTimestamp();
  try {
    await target.send(dmembed);
  } catch (err) {
    console.log(`Could not send DM to ${target.user.tag}: ${err}`);
  }

  // Execute ban and send confirmation
  await target.ban({reason: reason});
  await message.channel.send(`**${message.author.tag}** banned **${target.user.tag}** indefinitely.\nReason: *${reason}*.`);

  // Send log embed to logs channel
  const reportChannel = message.guild.channels.cache.find(x => x.name === 'logs');
  if (reportChannel) {
    const logchat = new Discord.MessageEmbed()
     .setTitle("Member Banned")
     .addField("Target", `${target.user} (${target.user.id})`)
     .addField("Moderator", `${message.author} (${message.author.id})`)
     .addField("Reason", `${reason}`)
     .setColor("GREEN")
     .setFooter(`ID: ${Math.floor(Math.random() * 100000000000000)}`)
     .setTimestamp()
     .setThumbnail(target.user.displayAvatarURL());
    await reportChannel.send(logchat);
  } else {
    console.log("Logs channel not found!");
  }
 }
}

Key Changes Explained

  1. Proper Async Member Fetch:

    • We use await with guild.members.fetch(args[0]) to resolve the Promise and get a valid GuildMember object.
    • Added a try/catch block to handle invalid IDs or users not present in the server.
  2. Permission Check Restricted to Mentions:

    • We store the mentioned member in a separate variable, then only run the hasPermission check if this variable exists. This strictly follows your requirement to skip permission checks when using an ID.
  3. Robust Error Handling:

    • Wrapped the DM send attempt in a try/catch block to avoid crashes if the banned user has DMs disabled.
    • Added a check to confirm the logs channel exists before attempting to send the log embed.
  4. Clean Reason Parsing:

    • The reason is always parsed from the second argument onwards, whether you're using a mention or an ID, which keeps the command behavior consistent.

Additional Note

If you want to ban users who aren't currently in the server (using their ID), you can skip the member fetch step entirely and call guild.members.ban(args[0], { reason: reason }) directly. Let me know if you need help adjusting the code for that use case!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:54:05