Discord骰子机器人/roll命令报错排查求助
Discord骰子机器人CommandInvocationError问题排查与修复
问题概述
首次开发Discord骰子机器人,需求为:用户输入/roll 2d20+4时,机器人掷2次20面骰子,返回「最大点数+修正值」「总和+修正值」的结果。但执行/roll时Discord显示“应用未响应”,终端抛出lightbulb.errors.CommandInvocationError。
现有代码
import hikari import lightbulb import random disc_token="..." server_id="..." bot=lightbulb.BotApp( token=disc_token, default_enabled_guilds=int(server_id) ) @bot.command @lightbulb.command('roll',"Role dados (exemplo: 2d20+5)") @lightbulb.implements(lightbulb.SlashCommand) async def roll(ctx,play): die_split=play.split("d") final_split=die_split[1].split("+") n_die=int(die_split[0]) die=int(final_split[0]) extra=int(final_split[1]) play=[n_die,die,extra] best_roll=0 sum_roll=0 for i in range(n_die): actual_roll=random.randint(1,die) sum_roll=sum_roll+actual_roll if(actual_roll>best_roll): best_roll=actual_roll sum_roll=sum_roll+extra extra_roll=best_roll+extra play_print='Bigger: '+str(best_roll)+'+'+str(extra)+'='+str(extra_roll)+' | Sum: '+str(sum_roll) await ctx.respond(play_print) bot.run()
终端报错信息(中文翻译)
回溯(最近的调用最后): 文件 "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\lightbulb\app.py", 第1163行, 在 invoke_application_command中 await context.invoke() 文件 "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\lightbulb\context\base.py", 第328行, 在 invoke中 await self.command.invoke(self) 文件 "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\lightbulb\... raise new_exc lightbulb.errors.CommandInvocationError: 命令'roll'调用期间发生错误
问题原因分析
- 参数声明缺失:
roll函数的play参数未使用lightbulb.option装饰器标记,Slash命令无法识别该参数,导致调用时参数缺失触发异常。 - 输入格式无容错:直接通过字符串分割处理输入,未考虑用户输入不符合
NdN+N格式的情况(如无修正值、格式错误),一旦输入不符合预期会直接崩溃。 - 同步随机数风险:使用
random.randint同步生成随机数,在异步框架中可能引发潜在的线程阻塞问题。
修复后的代码
import hikari import lightbulb import re disc_token="..." server_id="..." bot=lightbulb.BotApp( token=disc_token, default_enabled_guilds=int(server_id) ) @bot.command @lightbulb.command('roll',"掷骰子(示例:2d20+5)") @lightbulb.implements(lightbulb.SlashCommand) @lightbulb.option("play", "输入骰子格式,如2d20+4", type=str) async def roll(ctx: lightbulb.SlashContext) -> None: play = ctx.options.play # 正则匹配骰子格式,兼容带/不带修正值的情况 pattern = r'^(\d+)d(\d+)(?:\+(\d+))?$' match = re.match(pattern, play) if not match: await ctx.respond("输入格式错误,请使用如`2d20+4`的格式,修正值可选") return n_die = int(match.group(1)) die = int(match.group(2)) extra = int(match.group(3)) if match.group(3) else 0 best_roll = 0 sum_roll = 0 for _ in range(n_die): # 使用hikari异步随机数生成器 actual_roll = await hikari.random.randint(1, die) sum_roll += actual_roll if actual_roll > best_roll: best_roll = actual_roll total_best = best_roll + extra total_sum = sum_roll + extra play_print = f"最大点数:{best_roll}+{extra}={total_best} | 总和:{sum_roll}+{extra}={total_sum}" await ctx.respond(play_print) bot.run()
关键修改说明
- 添加
@lightbulb.option装饰器,明确声明Slash命令的参数,让Discord正确接收用户输入。 - 使用正则表达式校验输入格式,兼容
3d6这类不带修正值的情况,格式错误时返回友好提示。 - 改用
hikari.random.randint异步生成随机数,符合异步编程模型,避免线程阻塞风险。 - 用f-string优化字符串拼接,提升代码可读性。
内容的提问来源于stack exchange,提问作者Mateus Rocha
相关产品推荐
相关产品推荐

