Discord.py on_message事件检测服务器所有者被@触发AttributeError错误求解
问题根因
你遇到的AttributeError: 'NoneType' object has no attribute 'mentioned_in'报错有三个核心诱因:
- 没有过滤私信场景:
on_message事件会响应所有私信、频道消息,私信场景下message.guild为None,调用message.guild.owner自然返回空值 mentioned_in传参错误:该方法要求传入完整的Message对象,你传入的message.content是字符串,就算Member不为空也会触发报错- 服务器所有者信息获取失败:即便在服务器场景下,如果你开启的
member intents未实际生效、或者机器人缺少服务器管理权限,也会导致message.guild.owner返回空值
修复方案
第一步:基础逻辑修正
在函数最开头先加边界判断,过滤不需要处理的场景,修正方法调用:
@client.listen("on_message") async def on_message(message): # 过滤机器人消息、私信消息,避免死循环和空值报错 if message.author.bot or not message.guild: return # 正确获取服务器所有者 guild_owner = message.guild.owner if not guild_owner: return # 正确调用mentioned_in方法,传入Message对象而不是内容字符串 if not guild_owner.mentioned_in(message): return user_id = message.author.id # 后续业务逻辑
第二步:修复其他隐藏问题
你的原有代码还存在多个可触发崩溃、逻辑错误的问题:
- 直接拼接SQL语句存在SQL注入风险,改为参数化查询
- 没有处理用户首次触发时数据库无记录的问题,需要新增默认计数
- 剩余封禁次数计算错误:原代码写的
5 - int(timedid)和你预期的10次触发封禁逻辑不符 - 频道发消息方法错误:
await message.send不存在,应该调用message.channel.send - 达到封禁阈值时没有实际调用封禁接口,仅发送了通知
完整修复后代码
@client.listen("on_message") async def on_message(message): # 过滤机器人消息、私信消息 if message.author.bot or not message.guild: return guild = message.guild guild_owner = guild.owner # 过滤无法获取所有者、未提及所有者的场景 if not guild_owner or not guild_owner.mentioned_in(message): return user_id = message.author.id cursor = ownerpingtime.cursor() # 参数化查询避免SQL注入 cursor.execute("SELECT ownerpingtime FROM ownerpingtime WHERE client_id = %s", (user_id,)) alldata = cursor.fetchall() # 处理首次触发无记录的情况,新增默认记录 if not alldata: cursor.execute("INSERT INTO ownerpingtime (client_id, ownerpingtime) VALUES (%s, 1)", (user_id,)) timedid = 1 else: timedid = alldata[0][0] + 1 cursor.execute("UPDATE ownerpingtime SET ownerpingtime = %s WHERE client_id = %s", (timedid, user_id)) ownerpingtime.commit() cursor.close() timetillban = 10 - timedid await message.delete() if timedid < 10: word = "time" if timedid == 1 else "times" await message.reply(f"{message.author}#{message.author.discriminator} ping this server owner `{timedid}` {word}, you have `{timetillban}` times left till you will be banned") else: # 实际调用封禁方法,可选添加封禁原因 await message.author.ban(reason="Pinged server owner 10 times") await message.channel.send(f"{message.author}#{message.author.discriminator} has been banned from {guild.name} for pinging guild owner 10 times") try: await message.author.send(f"You have been banned from {guild.name} for pinging guild owner 10 times") except: # 用户关闭私信的情况忽略报错 pass
额外注意事项
确认你在Discord开发者后台的机器人设置页中,已开启Server Members Intent开关,同时代码初始化客户端时已声明对应意图:
intents = discord.Intents.default() intents.members = True client = discord.Client(intents=intents) # 如果你用的是commands.Bot也是同理传入intents参数
同时确认机器人在服务器中拥有删除消息、封禁成员的权限,否则操作会触发权限报错
内容的提问来源于stack exchange,提问作者TheFlownery
相关产品推荐
相关产品推荐

