# Ussd v0.2.0 - Table of Contents

> Build Ussd (Unstructured Supplementary Service Data) applications in Elixir without breaking a sweat.

## Pages

- [Ussd](readme.md)
- [Guide](guide.md)
- [Changelog](changelog.md)
- [LICENSE](license.md)

## Modules

- [Ussd.Wordwrap](Ussd.Wordwrap.md): Splits long text into `width`-wide chunks for `truncate/1`.

- Core
  - [Ussd](Ussd.md): Build a USSD (Unstructured Supplementary Service Data) request/response cycle out
of `Ussd.State` modules.
  - [Ussd.Context](Ussd.Context.md): The per-request context for a USSD interaction: who is dialing in (`uid`), which
group/session the request belongs to (`gid`), what they typed (`input`), and any
extra values the caller wants states/actions to see (`bag`).

  - [Ussd.ContinuingMode](Ussd.ContinuingMode.md): The three ways a session can behave across a dropped call / redial
  - [Ussd.Menu](Ussd.Menu.md): A fluent builder for the text a `Ussd.State` renders back to the caller.
  - [Ussd.Record](Ussd.Record.md): Per-session storage, scoped to a `Ussd.Context`'s `uid`/`gid` and backed by a
pluggable `Ussd.Cache`.

- Flow contracts
  - [Ussd.Action](Ussd.Action.md): A one-shot decision point that runs once, with no screen shown to the caller, and
resolves to the next module in the flow.
  - [Ussd.Configurator](Ussd.Configurator.md): Groups repeated `Ussd.use_*/2` setup so it can be shared across controllers/entry
points instead of copy-pasted.
  - [Ussd.ContinueState](Ussd.ContinueState.md): Additional behaviour required of a state declared with `use Ussd.State, continue: true`.
  - [Ussd.ExceptionHandler](Ussd.ExceptionHandler.md): Turns an exception raised while running a flow into a message the caller sees,
instead of a dead session.
  - [Ussd.Pagination](Ussd.Pagination.md): Mix into a state alongside a `paginate/1` declaration to page a long listing
without hand-rolling the bookkeeping
  - [Ussd.State](Ussd.State.md): A screen in a USSD flow.

- Decisions
  - [Ussd.Decision](Ussd.Decision.md): Something that can look at the caller's raw input and say yes or no.
  - [Ussd.Decisions.Between](Ussd.Decisions.Between.md): Matches when `low <= input <= high` (numeric-aware, so `Between.new(1, 10)` matches
`"9"` and `"10"` correctly instead of comparing them as strings).

  - [Ussd.Decisions.Equal](Ussd.Decisions.Equal.md): Matches when the input equals `expected` (numeric-aware: `"7"` matches `7`).
  - [Ussd.Decisions.Fallback](Ussd.Decisions.Fallback.md): Always matches. Use as the last `transition/2` in a state to give it a default route.
  - [Ussd.Decisions.GreaterThan](Ussd.Decisions.GreaterThan.md): Matches when the input is greater than `expected` (numeric-aware).
  - [Ussd.Decisions.GreaterThanOrEqualTo](Ussd.Decisions.GreaterThanOrEqualTo.md): Matches when the input is greater than or equal to `expected` (numeric-aware).
  - [Ussd.Decisions.In](Ussd.Decisions.In.md): Matches when the input equals one of `values` (numeric-aware).
  - [Ussd.Decisions.IsNumeric](Ussd.Decisions.IsNumeric.md): Matches when the input parses fully as an integer or float.
  - [Ussd.Decisions.Length](Ussd.Decisions.Length.md): Matches when the input is exactly `length` characters long.
  - [Ussd.Decisions.LessThan](Ussd.Decisions.LessThan.md): Matches when the input is less than `expected` (numeric-aware).
  - [Ussd.Decisions.LessThanOrEqualTo](Ussd.Decisions.LessThanOrEqualTo.md): Matches when the input is less than or equal to `expected` (numeric-aware).
  - [Ussd.Decisions.NotBetween](Ussd.Decisions.NotBetween.md): Matches when the input is outside `[low, high]` (numeric-aware).
  - [Ussd.Decisions.NotEqual](Ussd.Decisions.NotEqual.md): Matches when the input does not equal `expected` (numeric-aware).
  - [Ussd.Decisions.NotIn](Ussd.Decisions.NotIn.md): Matches when the input equals none of `values` (numeric-aware).
  - [Ussd.Decisions.Regex](Ussd.Decisions.Regex.md): Matches when the input matches `pattern`, e.g. `Regex.new(~r/^[0-9]{4}$/)`.

- Responses
  - [Ussd.Response](Ussd.Response.md): Shapes the engine's result into whatever your gateway expects. Wired in via
`Ussd.use_response/2`, either as a module implementing this behaviour or as a
3-arity function `(context, message, terminating? -> term)`.
  - [Ussd.Responses.AfricasTalking](Ussd.Responses.AfricasTalking.md): Formats a response for the Africa's Talking USSD gateway.
  - [Ussd.Responses.Arkesel](Ussd.Responses.Arkesel.md): Formats a response for the Arkesel USSD gateway.
  - [Ussd.Responses.Moolre](Ussd.Responses.Moolre.md): Formats a response for the Moolre USSD gateway.
  - [Ussd.Responses.Nalo](Ussd.Responses.Nalo.md): Formats a response for the Nalo USSD gateway.
  - [Ussd.Responses.Nsano](Ussd.Responses.Nsano.md): Formats a response for the Nsano USSD gateway.
  - [Ussd.Responses.Speso](Ussd.Responses.Speso.md): Formats a response for the Speso USSD gateway.

- Cache
  - [Ussd.Cache](Ussd.Cache.md): The storage contract `Ussd.Record` (and therefore session state) is built on.
  - [Ussd.Cache.ETS](Ussd.Cache.ETS.md): Default `Ussd.Cache` implementation: a supervised GenServer owning a public, named
ETS table.

- Testing
  - [Ussd.Test](Ussd.Test.md): A fluent helper for exercising a USSD flow end-to-end in ExUnit tests, mirroring a
caller dialing in and replying screen by screen.

- Exceptions
  - [Ussd.Exceptions.ActiveStateNotFoundError](Ussd.Exceptions.ActiveStateNotFoundError.md): Raised when a session is marked as initialized but its active state is missing from the record.
  - [Ussd.Exceptions.GlobalIdentifierEmptyError](Ussd.Exceptions.GlobalIdentifierEmptyError.md): Raised when a `Ussd.Context` is built with an empty `gid`.
  - [Ussd.Exceptions.InvalidConfiguratorError](Ussd.Exceptions.InvalidConfiguratorError.md): Raised when `Ussd.use_configurator/2` is given a module that doesn't implement `Ussd.Configurator`.
  - [Ussd.Exceptions.InvalidContinueStateError](Ussd.Exceptions.InvalidContinueStateError.md): Raised when continuing mode is `:confirm` but no valid continuing state (`continue: true`, with `confirm/0`) was given.
  - [Ussd.Exceptions.InvalidContinuingModeError](Ussd.Exceptions.InvalidContinuingModeError.md): Raised when `Ussd.use_continuing_state/4` is given something other than `:start`, `:continue` or `:confirm`.
  - [Ussd.Exceptions.InvalidExceptionHandlerError](Ussd.Exceptions.InvalidExceptionHandlerError.md): Raised when `Ussd.use_exception_handler/2` is given something that isn't a 1-arity function or a `Ussd.ExceptionHandler` module.
  - [Ussd.Exceptions.InvalidInitialStateError](Ussd.Exceptions.InvalidInitialStateError.md): Raised when `Ussd.use_initial_state/2` is given a module that isn't a `Ussd.State`.
  - [Ussd.Exceptions.InvalidResponseError](Ussd.Exceptions.InvalidResponseError.md): Raised when `Ussd.use_response/2` is given something that isn't a 2-arity function or a `Ussd.Response` module.
  - [Ussd.Exceptions.InvalidStateError](Ussd.Exceptions.InvalidStateError.md): Raised when an `Ussd.Action` chain resolves to a module that isn't a `Ussd.State`.
  - [Ussd.Exceptions.NextStateNotFoundError](Ussd.Exceptions.NextStateNotFoundError.md): Raised when a `Ussd.State` has no `transition`, `back`, `paginate` or `terminate`
clause that matches the caller's input.

  - [Ussd.Exceptions.NoEncryptionKeyConfiguredError](Ussd.Exceptions.NoEncryptionKeyConfiguredError.md): Raised by `Ussd.Record.set_encrypted/4` and `get_encrypted/4` when no encryption key
is configured. Set `config :ussd, :encryption_key, "..."` (any length; it is hashed
down to an AES-256 key).

  - [Ussd.Exceptions.NoGettextBackendConfiguredError](Ussd.Exceptions.NoGettextBackendConfiguredError.md): Raised by `Ussd.Menu.trans/4` when no Gettext backend is configured.
  - [Ussd.Exceptions.NoInitialStateProvidedError](Ussd.Exceptions.NoInitialStateProvidedError.md): Raised by `Ussd.run/1` when no initial state was set via `Ussd.use_initial_state/2`.
  - [Ussd.Exceptions.UniqueIdentifierEmptyError](Ussd.Exceptions.UniqueIdentifierEmptyError.md): Raised when a `Ussd.Context` is built with an empty `uid`.

## Mix Tasks

- Mix tasks
  - [mix ussd.gen.action](Mix.Tasks.Ussd.Gen.Action.md): Generates a new `Ussd.Action` module.
  - [mix ussd.gen.configurator](Mix.Tasks.Ussd.Gen.Configurator.md): Generates a new `Ussd.Configurator` module.
  - [mix ussd.gen.decision](Mix.Tasks.Ussd.Gen.Decision.md): Generates a new `Ussd.Decision` implementation.
  - [mix ussd.gen.exception_handler](Mix.Tasks.Ussd.Gen.ExceptionHandler.md): Generates a new `Ussd.ExceptionHandler` module.
  - [mix ussd.gen.response](Mix.Tasks.Ussd.Gen.Response.md): Generates a new `Ussd.Response` module.
  - [mix ussd.gen.state](Mix.Tasks.Ussd.Gen.State.md): Generates a new `Ussd.State` module.
  - [mix ussd.graph](Mix.Tasks.Ussd.Graph.md):     mix ussd.graph MyApp.Ussd.States.Welcome
    mix ussd.graph MyApp.Ussd.States.Welcome --output flow.mmd
  - [mix ussd.lint](Mix.Tasks.Ussd.Lint.md):     mix ussd.lint
    mix ussd.lint MyApp.Ussd.States.Welcome
    mix ussd.lint --strict
  - [mix ussd.simulate](Mix.Tasks.Ussd.Simulate.md):     mix ussd.simulate MyApp.Ussd.States.Welcome
    mix ussd.simulate MyApp.Ussd.States.Welcome --phone 233200000000 --response Ussd.Responses.AfricasTalking

