使用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
相关产品推荐
相关产品推荐

