Discord.py机器人在DM中发送消息时出现403权限缺失错误的求助
嘿,我刚好碰到过类似的Discord DM权限问题,来帮你捋一捋!你现在的情况是机器人在DM里触发斜杠命令后,能通过interaction.response.send_message回复,但直接调用interaction.channel.send就报403错误,而且还需要找到不用历史记录读取用户消息的方法,对吧?
先说说发送消息的403问题
你打印的权限显示send_messages=True但实际发送失败,这是因为Discord的DM场景里,直接频道消息权限和交互上下文权限是分开的。当用户触发斜杠命令时,机器人获得的是这个交互会话的临时权限,允许你用interaction.response或者后续的followup发送消息,但直接调用channel.send需要机器人拥有独立的DM发送权限——这可能因为用户隐私设置(比如用户没允许机器人主动发消息)或者权限配置的细节导致失败。
最快的解决办法:用交互跟进消息替代channel.send
直接把你代码里的await interaction.channel.send("Hello 2!")改成:
await interaction.followup.send("Hello 2!")
因为跟进消息是基于用户触发的命令上下文,Discord会默认允许这种消息发送,不会触发权限错误。如果需要延迟回复,也可以先调用await interaction.response.defer()(告诉Discord你要稍后回复),再用跟进消息发送内容。
另外再检查两个配置细节:
- 开发者门户里,机器人的
botScope必须勾选,同时权限里要确保开启Send Messages(虽然DM场景权限逻辑特殊,但这是基础配置) - 确认用户没有在Discord里把你的机器人拉黑或者设置成“不接收消息”(用户可以在机器人资料页调整这个设置)
再说说不用历史记录读取消息的方法
如果你不想用channel.history或last_message,可以用wait_for事件来监听用户的回复,而且可以限定只监听当前用户在当前DM频道的消息,非常精准:
给你的Start命令加一段监听逻辑(记得先导入asyncio库):
import asyncio @bot.tree.command(name="start",description="Start a game!") async def Start(interaction:discord.Interaction, players: int=2): await interaction.response.send_message("Hello! Please reply with your choice.") # 定义检查条件:只接收当前用户在当前DM频道的消息 def check(msg): return msg.author == interaction.user and msg.channel == interaction.channel try: # 等待用户回复,超时时间设为60秒 user_reply = await bot.wait_for('message', check=check, timeout=60.0) await interaction.followup.send(f"You said: {user_reply.content}") except asyncio.TimeoutError: await interaction.followup.send("You didn't reply in time!")
注意:用这个方法需要开启message_content意图——你得在开发者门户的Bot页面找到Message Content Intent并勾选,同时代码里的Intents要包含它:
# 要么用全量Intents intents = discord.Intents.all() # 要么明确开启需要的意图 # intents = discord.Intents.default() # intents.message_content = True bot = commands.Bot(command_prefix="/", intents=intents)
你的原始代码(方便参考)
import discord from discord.ext import commands bot = commands.Bot(command_prefix="/", intents=discord.Intents.all()) @discord.app_commands.allowed_installs(guilds=True, users=True) @discord.app_commands.allowed_contexts(guilds=True, dms=True, private_channels=True) @bot.tree.command(name="start",description="Start a game!") async def Start(interaction:discord.Interaction, players: int=2): print(f"{interaction.channel.permissions_for(interaction.channel.me).send_messages=}") await interaction.response.send_message("Hello!") await interaction.channel.send("Hello 2!") @bot.event async def on_ready(): print("Bot is online!") await bot.tree.sync() bot.run(token)
补充你提供的场景说明
- 运行场景:尝试让应用工作的DM窗口与斜杠命令界面
- Scope设置:机器人在开发者门户中已勾选的Scope选项
备注:内容来源于stack exchange,提问作者Abyss

