Skip to content

risa.context

The contexts handlers and hooks answer interactions through.

ErrorHandler

A function Client.error_handler registers: it takes a ClickFailure, then anything to inject.

ClickFailure

ClickFailure(ctx: ComponentContext, error: Exception, stage: FailureStage)

Bases: Struct

A click that failed, as the functions Client.error_handler registers receive it.

Attributes:

  • ctx (ComponentContext) –

    The context of the click. It has no view state, as in View.on_outdated: answer with respond, edit without interactive components or replace, and on a view with durable fields rerender() raises NoViewError. respond continues what was sent before the failure, as it would in the handler.

  • error (Exception) –

    The exception.

  • stage (FailureStage) –

    Where it was raised.

ComponentContext

ComponentContext(
    interaction: ComponentInteraction,
    *,
    rest: RESTClient,
    meta: ViewMeta,
    build: Callable[[View, Snowflake], Awaitable[Rendered]],
    gate: ResponseGate | None = None,
    slot: ViewSlot | None = None,
)

Bases: Context[ComponentInteraction]

The context of a click on one of a view's components.

A handler answers through it: rerender() redraws the message from the view's state, edit(...) replaces it with another layout, and respond(...) sends a new message. risa makes one per click.

message property

message: Message

The message the component is on, if any.

resolved property

resolved: ResolvedOptionData | None

The users, members, roles and channels picked in an entity select menu, or None.

values property

values: Sequence[str]

The values picked in a select menu; empty for a button.

edit async

edit(layout: Layout) -> None

Replace the message with layout, keeping the view's state on it.

For a screen the view's render does not draw, such as a confirmation or a closing message. A layout without interactive components ends the view, since nothing on it can be clicked any more. Like rerender(), it saves the view's state.

Parameters:

  • layout (Layout) –

    The new layout: one top-level component, or several in order.

Raises:

  • NoViewError –

    If the layout has interactive components and the view has durable fields, but this context has no view state, as in on_outdated and on_state_missing, or if replace() gave the message to another view.

  • EphemeralOriginError –

    If the message is ephemeral and the interaction was answered with a new message.

  • StateOverflowError –

    If an InMessage view's state does not fit the layout's components.

  • StateConflictError –

    If another process saved the view's state first. The view then holds that state.

  • StateUnreadableError –

    If another process saved the view's state first, in a form this code cannot read.

replace async

replace(view: View) -> None

Turn the message into another view, which answers its clicks from here on.

It builds view as Client.build does, so a view in a store gets a record of its own. This view's state is not saved, also not when the handler returns, and its record stays until its ttl runs out. If the message cannot be edited, the new view's record stays the same way and this view keeps the message. Afterwards rerender() and edit() of this context raise NoViewError, since the message is no longer this view's; edit only ever shows this view's own components.

Parameters:

  • view (View) –

    The view to show, an instance of a registered class.

Raises:

rerender async

rerender() -> None

Redraw the message from the view's current state, and save that state.

Every rerender is a commit. InMessage state is written into the message itself; InStore state goes to the store first, then the message is edited. A change made without calling it is saved when the handler returns, but that save can only log a failure; call it yourself, before any respond(), where a failure must be handled.

Raises:

  • NoViewError –

    If the view has durable fields but this context has no view state, as in on_outdated and on_state_missing, or if replace() gave the message to another view.

  • EphemeralOriginError –

    If the message is ephemeral and the interaction was answered with a new message.

  • StateOverflowError –

    If an InMessage view's state no longer fits its components.

  • StateConflictError –

    If another process saved the view's state first. The view then holds that state, so the handler can apply its change again and rerender.

  • StateUnreadableError –

    If another process saved the view's state first, in a form this code cannot read.

  • StateNotFoundError –

    If an InStore view's record disappeared while the handler ran.

Context

Context(
    interaction: T, *, rest: RESTClient, gate: ResponseGate | None = None
)

What a handler or hook gets for the interaction it answers.

channel_id property

channel_id: Snowflake

The id of the channel the interaction happened in.

custom_id property

custom_id: str

The custom_id of the component that was used.

guild_id property

guild_id: Snowflake | None

The id of the guild the interaction happened in, or None outside a guild.

interaction property

interaction: T

The interaction being answered.

member property

member: InteractionMember | None

The member who used the component, or None outside a guild.

message property

message: Message | None

The message the component is on, if any.

responded property

responded: bool

Whether the interaction has its initial response.

rest property

rest: RESTClient

The REST client risa answers through.

user property

user: User

The user who used the component.

acknowledge async

acknowledge(*, thinking: bool = False, ephemeral: bool = False) -> None

Acknowledge the interaction like defer, unless it already has its initial response.

Where defer raises, this does nothing, so it is safe to call whatever happened before.

Parameters:

  • thinking (bool, default: False ) –

    Show a "thinking..." message.

  • ephemeral (bool, default: False ) –

    Show that message only to the user who clicked.

defer async

defer(*, thinking: bool = False, ephemeral: bool = False) -> None

Acknowledge the interaction now and answer it later.

By default the acknowledgement is silent, and the answer is a rerender() or an edit() of the message. With thinking=True, Discord shows a "thinking..." message that the next respond() takes the place of.

Parameters:

  • thinking (bool, default: False ) –

    Show a "thinking..." message.

  • ephemeral (bool, default: False ) –

    Show that message only to the user who clicked.

Raises:

respond async

Send a message in answer to the interaction.

The first response answers the interaction itself; every later one is a follow-up message. After a thinking message, the first one replaces it, and keeps its visibility whatever ephemeral and tts say. Apart from ephemeral, the parameters are those of hikari's create_interaction_response and execute_webhook, which describe them in full.

Parameters:

Returns:

  • Response –

    The message, to fetch, edit or delete later.

FailureStage

Bases: StrEnum

Where a click failed, as ClickFailure.stage names it.

Attributes:

  • HANDLER –

    The handler raised.

  • LOAD –

    The view's load raised, so the handler never ran.

  • ON_OUTDATED –

    View.on_outdated raised.

  • ON_STATE_MISSING –

    View.on_state_missing raised.

  • STATE –

    The view's state could not be reached before any of the bot's code ran: the store failed or is missing, its lock timed out, or the codec's extra is not installed.

Response

Response(
    rest: RESTClient,
    interaction: ComponentInteraction | ModalInteraction,
    message: Message | None,
)

A message sent with respond(), to fetch, edit or delete later.

delete async

delete() -> None

Delete the message.

edit async

Edit the message.

The parameters are those of hikari's edit_interaction_response, which describes them in full. Every edit sends the mention settings, so one left out switches that mention parsing off.

Parameters:

Returns:

  • Message –

    The message as it is now.

fetch async

fetch() -> Message

Fetch the message as it is now.

ResponseGate

ResponseGate(
    lock: Lock = ...,
    acknowledged: Event = ...,
    response: _InitialResponse = NONE,
    adopted: bool = False,
)

Bases: Struct

Whether an interaction has been answered, shared by everything that answers it.

risa makes one per interaction, so a handler and the auto-defer watchdog never both send the initial response.

Attributes:

  • lock (Lock) –

    Held while the initial response is decided and sent.

  • acknowledged (Event) –

    Set once nothing more is owed to the REST listener: the initial response went out, or risa has finished with the interaction.

  • response (_InitialResponse) –

    Which initial response the interaction got.

  • adopted (bool) –

    Whether the click routed to a view, rather than being left to another listener.

responded property

responded: bool

Whether the interaction has its initial response.