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

如何在Discord.py中调用函数?调用warn函数遇属性错误求助

问题分析与解决方案

错误根源

你遇到的AttributeError: 'str' object has no attribute 'name'本质是两个问题导致:

  1. 直接调用作为hybrid_command的warn函数时,错误传入了未定义的ctx变量(该变量可能在其他上下文被定义为字符串,导致warn函数的member参数被错误的字符串填充)。
  2. warn作为命令函数,依赖commands.Context对象才能正常运行,但on_message事件中并没有这个对象,直接调用命令函数不符合Discord.py的设计逻辑。

另外,代码里guild.get_member(message.author.id)属于冗余操作,message.author本身就是当前消息发送者的discord.Member对象,无需额外查询。


解决方案一:将警告逻辑抽为通用异步函数(推荐)

把警告逻辑从命令函数中分离,做成可复用的异步函数,既可以被命令调用,也能在on_message事件中直接使用:

async def send_warning(message: discord.Message, member: discord.Member):
    # 优先尝试给用户发私信警告
    try:
        await member.send(f"Please, {member.name} do not send any form of bad words, Thank you!")
    except discord.Forbidden:
        # 用户关闭私信时,在消息频道公开警告
        await message.channel.send(f"{member.mention}, please do not send any form of bad words, Thank you!")

# 保留warn命令,调用通用警告函数
@bot.hybrid_command()
async def warn(ctx: commands.Context, member: discord.Member):
    await send_warning(ctx.message, member)
    await ctx.send(f"Warning sent to {member.name}!", ephemeral=True)

@bot.event
async def on_message(message):
    guild = bot.get_guild(SEVER_ID)
    if guild is None:
        print("No Guild")
        return
        
    channel = guild.get_channel(REPORT_CHANNEL)

    if message.author == bot.user:
        return

    result = profanity.contains_profanity(message.content)

    if result:
        await channel.send(f"**Message: **{message.content} | **User: **{message.author.name}")
        await channel.send("<@&1284787770874658939>")
        # 直接使用message.author作为成员对象
        await send_warning(message, message.author)
        await message.delete()

    # 必须放在事件末尾,否则会导致命令无法被处理
    await bot.process_commands(message)

解决方案二:通过bot.invoke调用命令(不推荐)

如果坚持要直接调用warn命令,需要手动构建命令上下文,使用bot.invoke方法触发命令:

@bot.hybrid_command()
async def warn(ctx: commands.Context, member: discord.Member):
    await ctx.send(f"Please, {member.name} do not send any form of bad words, Thank you!", ephemeral=True)

@bot.event
async def on_message(message):
    guild = bot.get_guild(SEVER_ID)
    if guild is None:
        print("No Guild")
        return
        
    channel = guild.get_channel(REPORT_CHANNEL)

    if message.author == bot.user:
        return

    result = profanity.contains_profanity(message.content)

    if result:
        await channel.send(f"**Message: **{message.content} | **User: **{message.author.name}")
        await channel.send("<@&1284787770874658939>")
        # 构建命令上下文并调用warn命令
        ctx = await bot.get_context(message)
        await bot.invoke(ctx, f"warn {message.author.mention}")
        await message.delete()

    await bot.process_commands(message)

关键注意事项

  • await bot.process_commands(message)必须放在on_message事件的最后,否则会导致部分命令无法被Discord.py处理。
  • 发送警告时加入异常捕获,避免因用户关闭私信权限导致报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:35:02