Search code examples
pythondiscord

Problem creating a discord bot for rolling dice


This is my first trying creating a discord bot. I want it to work like this:

User:

/roll 2d20+4

Then my bot will roll 2d20, save the sum and the bigger. Finally, it will print like this:

Output:

Bigger: 16+4=20 | Sum: 23+4=27.

This is the code I have:

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()

What is happening:

The bot is working (I tested some basic commands, like "Hello World" and works fine), but when I try to run the /roll command, for the discord user it shows: "! The app did not answered". At my terminal, the error was displayed like this:

Traceback (most recent call last): File "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\lightbulb\app.py", line 1163, in invoke_application_command await context.invoke() File "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\lightbulb\context\base.py", line 328, in invoke await self.command.invoke(self) File "C:\Users\MateusRochaQSOFT\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\ligh raise new_exc lightbulb.errors.CommandInvocationError: An error occurred during command 'roll' invocation

What could be wrong?


Solution

  • I think you're defining your options wrong for using the lightbulb package. You have to define the options using the @lightbulb.option decorator and can then access them via ctx.options. Where the name of the option is the property you can get.

    @bot.command
    @lightbulb.option("play", "dice roll")
    @lightbulb.command('roll',"Role dados (exemplo: 2d20+5)")
    @lightbulb.implements(lightbulb.SlashCommand)
    async def roll(ctx):
        play = ctx.options.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 = f"Bigger: {best_roll} + {extra} = {extra_roll} | Sum: {sum_roll}"
        await ctx.respond(play_print)
    
    bot.run()
    

    Found in the documentation here. You can access the play variable using ctx.options.play.

    I've also formatted the code to use PEP8 formatting and I used f-strings in place of the string concatenation that you were doing.

    You can also use the pass_options parameter in @lightbulb.command to pass all the defined options (via decorators) as keyword arguments.

    Like this:

    @bot.command
    @lightbulb.option("play", "dice roll")
    @lightbulb.command('roll',"Role dados (exemplo: 2d20+5)", pass_options=True)
    @lightbulb.implements(lightbulb.SlashCommand)
    async def roll(ctx, play):
    

    This way you don't need to do play = ctx.options.play.