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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:05:38