Getting Started

Architecture

A single bot process runs everything on the community side and serves a private REST API. The KSP mod is the only client of that API.

One process, two servers

The entry point starts the Discord bot and a uvicorn-hosted FastAPI server as concurrent asyncio tasks in the same process. The bot handles Discord interactions; the API handles requests from the game. They share the same in-memory data layer.

Process diagram: bot, API server and data layer

Image placeholder · 16/9

Data flow

User data, namely XP, balance, message counts, unlocked levels and language preference, lives in Firestore under guilds/{guild_id}/users/{user_id} and is mirrored in an in-memory dictionary. Writes are buffered and flushed on a timer; a local JSON file acts as a fallback cache.

Data layout (Firestore)
guilds/{guild_id}/users/{user_id}   # XP, balance, levels, language
contracts/                          # contract documents
corps/                              # player corporations
weekly_missions/                    # generated weekly objectives
mission_classifications/            # cached AI results (1 per week)

Sync vs. async

Firestore access through the firebase-admin SDK is synchronous, while Discord and API handlers are async. Write operations are wrapped so they can be awaited; simple reads stay synchronous.

Mind the boundary

Use the async helpers for writes (for example await store.add_balance(...)). Reads such as store.get_user(...) are plain synchronous calls.

The mimic system

The bot patches three internal discord.py dispatch points so an administrator can act as another user, with the swapped identity applied before any handler runs. Code that needs the genuine caller reads it back from interaction extras.

# Recover the real administrator behind a mimicked interaction
real_user = interaction.extras.get("_mimic_real_user")