服务更新时自动发消息至Discord的实现及sendMessage调用失败问题
Discord Bot 无法调用 sendMessage 问题解决
问题根源
bot.run()是阻塞式函数,一旦调用就会持续运行Bot的事件循环,后续代码完全没有执行机会。- 代码同时创建了
discord.Client和commands.Bot两个实例,完全冗余——commands.Bot本身就是discord.Client的子类,重复实例化会造成资源冲突。 sendMessage是异步方法,不能像普通同步函数那样直接调用,必须在异步事件循环内执行。
修复后的完整代码
import discord import asyncio from discord.ext import commands class DiscordBot: def __init__(self): self.token = "你的Bot令牌" self.imageFolder = "folder" intents = discord.Intents.default() intents.message_content = True intents.members = True # 只保留一个Bot实例,删除多余的Client self.bot = commands.Bot(command_prefix="!", intents=intents, description="Một con bot Ree đến từ stock-chat") # 绑定Bot就绪事件,确保Bot完全启动后再执行发送操作 @self.bot.event async def on_ready(): print(f"已登录:{self.bot.user}") # Bot就绪后直接触发消息发送 await self.sendMessage("服务更新通知!") async def sendMessage(self, content_message): # 遍历所有服务器的非机器人成员发送消息 for guild in self.bot.guilds: for member in guild.members: if not member.bot: try: await member.send(content_message) print(f"已发消息给 {member.name}") except discord.Forbidden: print(f"发消息给 {member.name} 失败:无权限") def runbot(self): # 启动Bot,此方法会阻塞当前线程 self.bot.run(self.token, reconnect=True) # 启动Bot bot_discord = DiscordBot() bot_discord.runbot()
扩展:外部事件触发消息发送
如果需要在服务更新时主动触发消息(而非Bot启动时发送),可以给类添加一个触发方法,通过线程安全的方式调用异步函数:
# 在DiscordBot类中新增此方法 def trigger_update_notice(self, content): # 确保Bot已就绪再执行发送 if self.bot.is_ready(): asyncio.run_coroutine_threadsafe(self.sendMessage(content), self.bot.loop)
之后在你的服务更新代码里,调用bot_discord.trigger_update_notice("服务已完成更新!")即可,注意这个调用要在单独线程中执行,避免阻塞Bot的事件循环。
注意事项
批量给成员发私信容易触发Discord的频率限制,建议要么给每个发送操作添加await asyncio.sleep(1)的延迟,要么优先选择发送到指定服务器频道,而非私信。
内容的提问来源于stack exchange,提问作者Rinn
相关产品推荐
相关产品推荐

