ExGram.FSM (ExGram FSM v0.1.0)

Copy Markdown View Source

Finite State Machine / conversation state management for ExGram Telegram bots.

Quick start

defmodule MyBot do
  use ExGram.Bot, name: :my_bot
  use ExGram.Router
  use ExGram.FSM,
    storage: ExGram.FSM.Storage.ETS,
    flows: [MyBot.RegistrationFlow, MyBot.SettingsFlow],
    on_invalid_transition: :log

  command("register")

  scope do
    filter :command, :register
    handle &MyBot.Handlers.register/1
  end

  scope do
    filter :fsm_flow, :registration
    filter :fsm_state, :get_name
    filter :text
    handle &MyBot.Handlers.got_name/1
  end

  scope do
    handle &MyBot.Handlers.fallback/1
  end
end

The :fsm_flow and :fsm_state filter aliases are registered automatically when use ExGram.FSM detects that use ExGram.Router was also called. Use them to scope routes to a specific flow and step.

Without ExGram.Router

Pattern-match on context.extra.fsm directly in handle/2 clauses:

defmodule MyBot do
  use ExGram.Bot, name: :my_bot
  use ExGram.FSM,
    storage: ExGram.FSM.Storage.ETS,
    flows: [MyBot.RegistrationFlow]

  command("register")

  def handle({:command, :register, _}, context) do
    context |> start_flow(:registration) |> answer("What's your name?")
  end

  def handle({:text, name, _}, %{extra: %{fsm: %ExGram.FSM.State{flow: :registration, state: :get_name}}} = context) do
    context
    |> update_data(%{name: name})
    |> transition(:get_email)
    |> answer("Got it! What's your email?")
  end

  def handle(_, context), do: context
end

Options

OptionTypeDefaultDescription
storage:moduleExGram.FSM.Storage.ETSStorage backend
flows:list of modules[]Flow modules (each using use ExGram.FSM.Flow)
on_invalid_transition:atom or {m, f}:raiseInvalid transition policy
key:moduleExGram.FSM.Key.ChatUserKey adapter (see ExGram.FSM.Key)

on_invalid_transition policies

PolicyBehavior
:raise (default)Raises ExGram.FSM.TransitionError
:logLogs a warning, returns context unchanged
:ignoreSilent no-op, returns context unchanged
{Module, :function}Calls Module.function(context, from, to)

Imported helpers

use ExGram.FSM automatically imports these functions:

  • start_flow/2 - start a named flow (sets flow + default state + clears data)
  • get_flow/1 - read current flow name atom
  • get_state/1 - read current state atom within the active flow
  • get_data/1 - read current data map
  • set_state/2 - force set state within the active flow (no transition validation)
  • set_state/3 - force set flow + state (escape hatch, ignores conflicts)
  • transition/2 - set state with validation against the active flow's transitions
  • update_data/2 - merge map into FSM data
  • clear_flow/1 - reset flow, state, and data entirely

Summary

Functions

add_router_alias(module, alias_name, filter_module)