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

使用JSON存储的discord.py Hybrid警告命令报错求助

解决discord.py Hybrid命令中VAR_POSITIONAL参数报错及协程未等待问题

问题描述

尝试用JSON文件实现discord.py的warn命令时出现报错,不清楚协程未等待的原因,错误回溯如下:

Traceback (most recent call last):
  File "/home/container/main.py", line 261, in <module>
    async def warn(ctx,member:discord.Member,*reason:str):
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 289, in decorator
    result = hybrid_command(name=name, *args, with_app_command=with_app_command, **kwargs)(func)
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/hybrid.py", line 888, in decorator
    return HybridCommand(func, name=name, with_app_command=with_app_command, **attrs)  # type: ignore  # ???
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/hybrid.py", line 509, in __init__
    HybridAppCommand(self) if self.with_app_command else None
  File "/home/container/.local/lib/python3.9/site-packages/discord/ext/commands/hybrid.py", line 306, in __init__
    super().__init__(
  File "/home/container/.local/lib/python3.9/site-packages/discord/app_commands/commands.py", line 677, in __init__
    self._params: Dict[str, CommandParameter] = _extract_parameters_from_callback(callback, callback.__globals__)
  File "/home/container/.local/lib/python3.9/site-packages/discord/app_commands/commands.py", line 393, in _extract_parameters_from_callback
    param = annotation_to_parameter(resolved, parameter)
  File "/home/container/.local/lib/python3.9/site-packages/discord/app_commands/transformers.py", line 863, in annotation_to_parameter
    raise TypeError(f'unsupported parameter kind in callback: {parameter.kind!s}')
TypeError: unsupported parameter kind in callback: VAR_POSITIONAL
sys:1: RuntimeWarning: coroutine 'Command.__call__' was never awaited

原代码如下:

@client.hybrid_command(name = "warn", with_app_command=True, description="Warn a user")
@commands.has_permissions(ban_members=True)
async def warn(ctx,member:discord.Member,*reason:str):
    author = ctx.author
    if not reason:
        await ctx.send("Please provide a reason")
        return
        reason = ' '.join(reason)
        await ctx.send(f'**{member.mention} has been warned by {author.name}.**')
        await member.send(f'You have been warned in **{ctx.guild.name}** by **{author.name}**.')
        for current_user in report['users']:
            if current_user['name'] == member.name:
                current_user['reasons'].append(reason)
                break
    else:
        report['users'].append({
           'name':member.name,
           'reasons': [reason,]
        })
        with open('reports.json','w+') as f:
            json.dump(report,f) 
            
@client.hybrid_command(name = "warnings", with_app_command=True, description="View the warnings of a user", aliases=["punishments", "warns"])
async def warnings(ctx,member:discord.Member):
    for current_user in report['users']:
        if member.name == current_user['name']:
            await ctx.send(f"**{member.name} has been reported {len(current_user['reasons'])} times : {','.join(current_user['reasons'])}**")
            break
        else:
            await ctx.send(f"**{member.name} has never been warned**")    

解决方案

1. 修复VAR_POSITIONAL参数错误

discord.py的Hybrid命令(同时支持前缀和Slash命令)不支持*reason:str这种可变位置参数,因为Slash命令的参数系统无法解析这种格式。

  • 修改参数为reason: str = None,允许理由为空,再在代码内处理空值情况。

2. 修正代码逻辑错误

原代码存在两处逻辑问题:

  • if not reason:分支里的return语句位置错误,导致后续处理代码永远无法执行;
  • JSON写入逻辑分支颠倒,且未统一处理保存操作。
  • 调整后:空理由时发送提示后直接返回;非空时执行通知、更新记录、保存文件的完整流程。

3. 协程未等待警告的处理

该警告是由于参数错误导致命令注册失败,内部协程未被正确触发,解决上述参数和逻辑问题后,警告会自动消失。

修复后的完整代码

import json
import discord
from discord.ext import commands

# 初始化警告记录结构,优先从文件读取,不存在则创建空结构
try:
    with open('reports.json', 'r') as f:
        report = json.load(f)
except FileNotFoundError:
    report = {"users": []}

@client.hybrid_command(name="warn", with_app_command=True, description="警告用户")
@commands.has_permissions(ban_members=True)
async def warn(ctx, member: discord.Member, reason: str = None):
    author = ctx.author
    if not reason:
        await ctx.send("请提供警告理由")
        return
    
    warn_reason = reason.strip()
    
    # 发送服务器内通知
    await ctx.send(f'**{member.mention} 已被 {author.name} 警告。**')
    # 尝试发送私信通知,处理用户关闭私信的情况
    try:
        await member.send(f'你在 **{ctx.guild.name}** 被 **{author.name}** 警告,理由:{warn_reason}')
    except discord.Forbidden:
        await ctx.send(f'无法私信用户 {member.mention},对方可能关闭了私信权限。')
    
    # 更新警告记录
    user_found = False
    for current_user in report['users']:
        if current_user['name'] == member.name:
            current_user['reasons'].append(warn_reason)
            user_found = True
            break
    if not user_found:
        report['users'].append({
            'name': member.name,
            'reasons': [warn_reason,]
        })
    
    # 保存记录到JSON文件
    with open('reports.json', 'w') as f:
        json.dump(report, f, indent=4) 

@client.hybrid_command(name="warnings", with_app_command=True, description="查看用户警告记录", aliases=["punishments", "warns"])
async def warnings(ctx, member: discord.Member):
    user_found = False
    for current_user in report['users']:
        if current_user['name'] == member.name:
            await ctx.send(f"**{member.name} 共有 {len(current_user['reasons'])} 条警告记录:{','.join(current_user['reasons'])}**")
            user_found = True
            break
    if not user_found:
        await ctx.send(f"**{member.name} 暂无警告记录**")    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:31:41