raito.plugins.scenes.scene module

class raito.plugins.scenes.scene.Scene(manager, state, *, data, step, base)[source]

Bases: Generic[TSceneData]

Per-update handle to an active scene, injected into every handler as scene.

Carries the typed draft (data) and the verbs to move between steps. One instance is built per update and discarded when the handler returns, so it never outlives a single message nor holds a resource.

Navigation only changes state: it saves the draft and switches the FSM step. It never sends anything — reply with the message you already have (await message.answer(...)), which exposes every Telegram option natively.

Parameters:
  • manager (SceneManager[TSceneData])

  • state (FSMContext)

  • data (TSceneData)

  • step (State | None)

  • base (dict[str, Any] | None)

data
async goto(target)[source]

Save the draft and switch to target.

Parameters:

target (State) – step to activate next

Raises:

ValueError – if target is not a step of this scene

Return type:

None

async next()[source]

Save the draft and advance to the next step (the first one, from entry).

Return type:

None

async back()[source]

Save the draft and return to the previous step.

Return type:

None

async retry()[source]

Stay on the current step, saving the draft.

Return type:

None

async finish()[source]

End the scene, clearing only its own FSM payload.

Return type:

None

async cancel()[source]

Alias of finish() for an explicit cancellation path.

Return type:

None

async escape()[source]

Cancel the scene and let this update reach the next matching handler.

Use this to let an unrelated command interrupt the scene, e.g. /start arriving mid-dialog. Combine with SceneRegistry.any() to catch it regardless of which step the user is on:

@mute.on_message.any(F.text.startswith("/"))
async def escape_on_any_command(scene: Scene[MuteData]) -> None:
    await scene.escape()

A plain cancel() would still swallow the update — nothing else gets a turn at it. escape clears the scene, then re-raises so aiogram keeps looking, exactly as if this handler had never matched (a real /start handler registered after this one still runs for the same update).

Return type:

NoReturn

async restart()[source]

Discard the current draft and start this scene over from its first step.

Return type:

None

async start(target, *, at=None, **data)[source]

End this scene and start target, seeding its draft from data.

The current payload is replaced by a fresh draft for target, validated against its SceneData. Send the target’s first prompt yourself, as with any navigation.

Parameters:
  • target (SceneManager[Any]) – scene to hand the dialog off to

  • at (State | None) – step to open target at; defaults to its first step

  • data (object) – initial fields for the target’s draft

Raises:

ValueError – if at is not a step of target

Return type:

None