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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:12:01