Standalone Anarchy Online market-tracking bot
A standalone Anarchy Online market-tracking bot: an asyncio AO chat
client for in-game market/mkt commands, a FastAPI control API for the
same functionality over HTTP, and a PostgreSQL-backed watch list that
polls item order books and auto-tracks popular items.
Two things run in one process:
uvicorn’s event loop — the HTTP control surface.The two sides never share state directly; a small bridge
(asyncio.run_coroutine_threadsafe) lets the API thread schedule work
onto the bot thread’s loop and await the result. Both the chat command
layer and the API routes are thin presentation layers over the exact
same business logic (MarketService) — a chat-originated market watch
and an API POST /watch/{aoid} end up calling the same code.
See src/aomarket/README.md for the full
module map and concurrency model, and the README in each submodule for
what it does:
aochat/ — AO chat protocol clientaodb/ — item lookup/search clientgmi/ — live order book clientautotrack/ — popular-item scraperdb/ — models and repositoriesmarket/ — core business logicbot/ — the bot thread and background loopsapi/ — the FastAPI control surfacecp .env.example .env # fill in AO_LOGIN/AO_PASSWORD/AO_CHARACTER to enable chat, or leave blank for API-only mode
docker compose up
This brings up Postgres and the bot together; the API is then available
at http://localhost:8000 (interactive docs at /docs).
Every setting is an environment variable, loaded by AppConfig
(src/aomarket/config.py):
| Variable | Default | Notes |
|---|---|---|
DATABASE_URL |
postgresql+asyncpg://aomarket:aomarket@localhost:55432/aomarket |
SQLAlchemy/asyncpg connection string. |
AO_LOGIN, AO_PASSWORD, AO_CHARACTER |
(blank) | Leave all blank to run in API-only mode. |
AO_CHAT_SERVER |
chat.d1.funcom.com |
|
AO_CHAT_PORT |
7105 |
|
AODB_API_URL |
https://aodb-api.ao.yeetbox.net |
Item lookup/search service. |
GMI_API_URL |
https://gmi.nadybot.org |
Live order book service. |
API_HOST |
0.0.0.0 |
|
API_PORT |
8000 |
|
LOG_LEVEL |
INFO |
Runtime behavior tuning (poll interval, auto-track on/off, subscription
limits, …) lives in the settings table instead, seeded with defaults
on startup — see db/README.md.
A Helm chart lives in charts/aomarket-bot
and is published to this repo’s own Helm repository on every release:
helm repo add aomarket-bot https://marketbot.ao.yeetbox.net/
helm repo update
helm install aomarket-bot aomarket-bot/aomarket-bot \
--set aomarketBot.secret.databaseUrl="postgresql+asyncpg://user:pass@host:5432/dbname"
It expects an external PostgreSQL database — the chart doesn’t bundle one. See the chart’s own README for the full values reference.
pip install -e ".[dev]"
docker compose up -d postgres
pytest
ruff check .
See tests/README.md for how the test suite is laid
out and what needs a live Postgres.
pyproject.toml requires Python >=3.12, but CI runs lint and the test
suite against a wider range on every push to main so regressions on
other versions surface early. Only 3.14 is a required check for
merging — the rest are informational (fail-fast: false, so one
version failing doesn’t block the others from reporting).
| Version | Lint | Tests |
|---|---|---|
| 3.11 | ||
| 3.12 | ||
| 3.13 | ||
| 3.14 (supported) | ||
| 3.15.0-rc.1 |
These reflect the most recent push to main (each matrix leg in
ci.yml publishes its own status to
gh-pages as a small JSON file, since GitHub’s own workflow badges only
report the workflow as a whole, not individual matrix legs).
Commits must follow Conventional Commits
(fix(component): …, feat(component): …, …) — enforced by CI and
required for semantic-release
to cut releases correctly.