#Dealing with buttons in Container components

1 messages · Page 1 of 1 (latest)

nocturne kite
#

I am trying to make an interface using the somewhat new Container functionality. Afaik, Miru doesn't support it (yet?), so I am building the Containers with raw Hikari.

hikari.impl.SectionComponentBuilder(
    accessory=hikari.impl.InteractiveButtonBuilder(
        style=hikari.ButtonStyle.SECONDARY,
        label="✏️",
        custom_id="banner_edit_base",
    ),
    components=[
        hikari.impl.TextDisplayComponentBuilder(content="Base"),
    ]
),

How do I create a view for this button to handle a user clicking it? Or maybe should I approach making this interface differently?

empty lava
nocturne kite
empty lava
#

Okay, so here is a basic handling of your above item, which should in theory create a new ephemeral message, with only that button.

import hikari
import os

bot = hikari.GatewayBot(os.environ["TOKEN"])

@bot.listen()
async def command_interaction(event: hikari.ComponentInteractionCreateEvent) -> None:
    if event.interaction.custom_id == "banner_edit_base":
        await event.interaction.create_initial_response(
            hikari.ResponseType.MESSAGE_CREATE,
            "Here is a response because you pressed a button!",
            flags=hikari.MessageFlag.EPHEMERAL,
        )

    else:
        print("This could be a miru interaction component, so be careful.")

I would also highly recommend adding this to your miru handler:

miru_client = miru.Client(
    ...,
    ignore_unknown_interactions=True,
)
nocturne kite
empty lava
#

yes.

nocturne kite
#

Ok and I think from that I can figure out all I can do, I'll let you know if I have any issues, thanks!

#

Oh wait

#

Will @loader.listener() work instead? (lightbulb)

#

I'm in an extension module so I don't have direct access to the bot

empty lava
#

yeah thats just the same thing but for lightbulb extensions

#

(I am like 80% sure of that, but you can just try it as well.)

nocturne kite
#

I am trying to edit the message when a button is clicked but it doesn't work :(


@loader.listener(hikari.ComponentInteractionCreateEvent)
async def banner_interaction(event: hikari.ComponentInteractionCreateEvent) -> None:
    button_id = event.interaction.custom_id
    if not button_id.startswith("banner_"):
        return # Not a banner event
    keywords = button_id.split("_")[1:]
    banner = banner_designs[event.interaction.user.id]
    match keywords[0]:
        case "select": await event.interaction.edit_initial_response(None)
hikari.errors.NotFoundError: Not Found 404: (10015) 'Unknown Webhook' for https://discord.com/api/v10/webhooks/abunchofnumbersandletters/messages/@original
heady fractal
#

When you receive an interaction, you first need to respond to it

#

that 404 is due to your edit being queued until after your initial response is created, which gets invalidated after 3s

#

what you want is to create an initial response with the type being set to MESSAGE_UPDATE

nocturne kite
#

Oh wait it's a create event intensethonk

heady fractal
#

ComponentInteractionCreateEvent :P

nocturne kite
#

Yeah I wanted a button click

heady fractal
#

yeah

#

that creates an interaction event

nocturne kite
#

I just copied the code Platy sent

heady fractal
#

which you are properly handling

nocturne kite
#

Then I'm confused

#

What do you mean by respond?

heady fractal
#

but the first response has to be done using create_initial_response

nocturne kite
#

Oh can I not edit the message without sending a new one?

heady fractal
#

there, in the type parameter, you can specify what that initial response will do

#

it can create a mesage

#

edit a previous message

#

or "defer" (which shows the "bot is thinking" message)

#
#

If it confuses you, then leave it

#

but might help you

#

I might extract it out of there at some point, idk

nocturne kite
#

Yeah the function names are definitely confusing lol

heady fractal
#

yeah, blame that one on Discord :P

#

Once you get used to it, its simple enough

#

Let us know if you need anything else!

nocturne kite
#

How do I handle errors from this modal? Can I somehow make the lightbulb error handler I have right now deal with them too?

heady fractal
#

Yeah, the lightbulb error handler should work

nocturne kite
#

Okay no my handler is definitely not invoked when the components raise an error:

@lightbulb_client.error_handler
async def handler(exc: lightbulb.exceptions.ExecutionPipelineFailedException) -> bool:
    ...
nocturne kite
#

@heady fractal 🥺

heady fractal
#

@astral vigil might be more suited for this

astral vigil
#

Someone give me tldr

heady fractal
#

@nocturne kite :)

nocturne kite
# astral vigil Someone give me tldr

I have buttons in the new Container components, and I handle them manually through hikari, listening to hikari.ComponentInteractionCreateEvent. Now I want to properly handle errors the get raised while handling such an event. Can I do it with lightbulb? The handler I have (whose signature I've sent just a couple messages above) doesn't seem to activate on Container components errors

#

Dealing with buttons in Container components

astral vigil
#

Lightbulb error handlers will never catch errors thrown during listeners

#

Use a try/except or a hikari error handler

heady fractal
#

ExceptionEvent might be what you are looking for

nocturne kite
#

Now another issue

#

Can I edit the Container components list and send it again?

#

Just manipulating message.components gives me AttributeError: 'TextDisplayComponent' object has no attribute 'build'

#

so I guess I have to pass builders into the components argument, and message.components gives me components that are already built? What do I do?

heady fractal
nocturne kite
#

I don't quite get what the solution is here

heady fractal
#

What are you trying to achieve?

nocturne kite
#

I want to add the error message as an embed at the bottom of my components

heady fractal
#

Make a function that returns your builder and allow passing a parameter to add the additional component

nocturne kite
heady fractal
#

In what cases wouldn't you know?

nocturne kite
#

In all cases! I'm making an error handler, handling a button being clicked in a container. The contents of said container can be very different

heady fractal
#

Oh wait

heady fractal
#

If so, you cant

#

It's a discord limitation

nocturne kite
#

Like here

heady fractal
#

Why edit the message and not send another ephemeral message?

nocturne kite
#

It has a cleaner look this way in my opinion

#

You don't have to click "hide the message" multiple times

#

Does the format Discord API expects from a bot sending messages differ from the format it sends messages to the bot? Why can't I use the components I received from Discord as-is?

heady fractal
heady fractal
nocturne kite
astral vigil
#

.execute

heady fractal
#

^

#

cant send ephemeral messages that way, but it will work

heady fractal
nocturne kite
nocturne kite
#

I ended up making my own unbuild() function to convert hikari.[…]Component thingies back to builders

#

Thanks for help anyways :)

astral vigil
#

execute allows for ephemeral msgs

nocturne kite
#

I just realized I might be wrong in adding a

    if not handled:
        raise exc_event.exception from None

at the end of my ExceptionEvent handler. Does the exception still get raised and logged as usual for any exception, even if a hikari handler catches it?

heady fractal
heady fractal
#

Does the exception still get raised and logged as usual for any exception, even if a hikari handler catches it?

No, if you handle it in the exception handler, it wont be logged

nocturne kite
heady fractal
#

Oh yeah

#

You can't reraise from ExceptionEvent

#

It's done to avoid infinite loops

nocturne kite
heady fractal
#

Basically never raise from an exception event handler unless you want to just print it to console

#

It will never call itself again

nocturne kite
#

I just wanted the red message to be a little more meaningful too, but I guess it's not possible