Skip to content

a-xp/fb-alchemy-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fb-alchemy-bot

A Facebook Messenger / Instagram DM chatbot that runs a small "alchemy" combination game: players send two symbols (emoji), and the bot tells them what those two ingredients make — or nudges them to try again if the combination is unknown.

It's a compact, fully-tested example of a webhook chatbot in async Rust (tokio + hyper), built with a clean ports-and-adapters layout so the game logic is completely decoupled from the Messenger platform.

How a conversation works

Each player has a session that walks through a small state machine, driven entirely by the messages they send:

                  "stop" (any time) ──────────────┐
                                                   ▼
  New ──▶ DecidingToJoin ──"yes"──▶ ChoosingOption  ...  Quit
   │           │  "no"                   │
 greeting    rules / bye          combo ─┤─ known   → result
                                         ├─ partial → "wrong combo"
                                         └─ garbage → "invalid input"

Matching is emoji-aware: combinations are compared order-independently and the Facebook variation selector (U+FE0F) is stripped, so ☕🍋 and 🍋 ☕️ resolve to the same result.

Architecture

Ports-and-adapters — the core domain knows nothing about Facebook or HTTP:

Module Role
core/processing Per-message state machine that advances a session and queues responses
core/game Game model: combination lookup, generic yes/no/stop matching, response templates
core/types Domain types and the port traits (ResponseSender, DefinitionsRepository, SessionRepository)
services/response Adapter: sends replies via the Facebook Graph API (/me/messages)
services/definitions Adapter: loads channels and games from JSON files
services/sessions Adapter: in-memory session store
handler Wires an incoming platform message to the domain and back out to the sender
fb_hook_srv The Messenger webhook server: verification handshake + event parsing

Because the platform is behind traits, the whole game is exercised in tests with mock senders and no network — see the tests modules (18 tests covering the state machine, emoji matching, and webhook parsing).

Game definitions

The bot is data-driven. DATA_DIR holds:

  • channels.json — the pages/accounts the bot serves, each with its Facebook page access token used to send replies. Treat this as a secret; the copy in test_resources contains placeholders only.
  • game-<n>.json — a game's results (each a combinationresult), optional custom responses (greeting, rules, …), and optional generic_answers (what counts as yes / no / stop).

Configuration

All configuration is environment-driven:

Variable Default Purpose
PORT 3021 Port the webhook server listens on
TOKEN MY_TEST_TOKEN Webhook verify token for the subscription handshake
DATA_DIR ./src/test_resources/data Directory with channels.json + game-*.json
RUST_LOG info Log level (env_logger)

The Messenger webhook is served at GET/POST /api/webhook.

Getting started

The toolchain is pinned with mise:

mise install        # installs the pinned Rust toolchain
mise run test       # run the test suite
mise run run        # start the webhook server on $PORT
mise run lint       # clippy (warnings denied)
mise run build      # optimized release binary

Or with cargo directly from backend/:

cd backend
cargo test
cargo run --bin server

Project layout

backend/         Rust crate (the bot)
  src/core/      domain: game rules + session state machine
  src/services/  adapters: FB sender, file repo, session store
  src/handler.rs platform ⇄ domain wiring
  src/fb_hook_srv.rs  Messenger webhook server
scripts/         Ansible deployment (static musl build, nginx + LetsEncrypt, systemd)

Deployment

scripts/ builds a fully static Linux binary inside the rust-musl-builder Docker image and ships it with Ansible: it provisions an nginx reverse proxy with LetsEncrypt TLS, a dedicated service user, and a systemd unit. Per-host inventory lives in scripts/hosts/ (gitignored). See scripts/deploy.sh.


A 2022 hobby project, kept as a small, self-contained example of an async-Rust chat bot with a clean, testable architecture.

About

Facebook Messenger / Instagram chatbot running an emoji 'alchemy' combination game — async Rust (tokio + hyper), clean ports-and-adapters architecture

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors