v0.0.28: BotFather-only registration, per-instance bot toggle, docs update

Security:
- Bot registration restricted to BotFather (requires botfather_token)
- Direct POST /v1/bot/register without BotFather auth → rejected

Deploy:
- systemd service reads /home/warzone/server.env for EXTRA_ARGS
- deploy/warzone-server.env.mequ: no bots (default)
- deploy/warzone-server.env.kh3rad3ree: --enable-bots
- setup.sh copies per-hostname env file

Docs updated:
- LLM_HELP.md: BotFather flow, plaintext bot messaging, E2E option, bridge
- LLM_BOT_DEV.md: botfather_token requirement, E2E mode, bridge section
- BOT_API.md: full BotFather flow, ownership, numeric IDs, webhook delivery
- SERVER.md: --enable-bots flag, per-instance config, bot system section
- USAGE.md: bot messaging, BotFather, bridge tool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-29 09:52:12 +04:00
parent 8603087afb
commit 76cac77259
14 changed files with 288 additions and 74 deletions

10
warzone/Cargo.lock generated
View File

@@ -2956,7 +2956,7 @@ dependencies = [
[[package]]
name = "warzone-client"
version = "0.0.27"
version = "0.0.28"
dependencies = [
"anyhow",
"argon2",
@@ -2989,7 +2989,7 @@ dependencies = [
[[package]]
name = "warzone-mule"
version = "0.0.27"
version = "0.0.28"
dependencies = [
"anyhow",
"clap",
@@ -2998,7 +2998,7 @@ dependencies = [
[[package]]
name = "warzone-protocol"
version = "0.0.27"
version = "0.0.28"
dependencies = [
"base64",
"bincode",
@@ -3023,7 +3023,7 @@ dependencies = [
[[package]]
name = "warzone-server"
version = "0.0.27"
version = "0.0.28"
dependencies = [
"anyhow",
"axum",
@@ -3053,7 +3053,7 @@ dependencies = [
[[package]]
name = "warzone-wasm"
version = "0.0.27"
version = "0.0.28"
dependencies = [
"base64",
"bincode",

View File

@@ -9,7 +9,7 @@ members = [
]
[workspace.package]
version = "0.0.27"
version = "0.0.28"
edition = "2021"
license = "MIT"
rust-version = "1.75"

View File

@@ -1,6 +1,6 @@
[package]
name = "warzone-protocol"
version = "0.0.27"
version = "0.0.28"
edition = "2021"
license = "MIT"
description = "Core crypto & wire protocol for featherChat (Warzone messenger)"

View File

@@ -236,6 +236,8 @@ struct RegisterBotRequest {
e2e: Option<bool>, // true = E2E bot, false/None = plaintext bot
#[serde(default)]
owner: Option<String>, // fingerprint of the bot creator
#[serde(default)]
botfather_token: Option<String>,
}
/// Register a bot and receive a token.
@@ -249,12 +251,25 @@ async fn register_bot(
State(state): State<AppState>,
Json(req): Json<RegisterBotRequest>,
) -> AppResult<Json<serde_json::Value>> {
// TODO: In production, only @botfather should be able to register bots.
// For v1, direct registration is allowed for development.
if !state.bots_enabled {
return Ok(Json(serde_json::json!({"ok": false, "description": "Bot API is disabled on this server. Use a server with --enable-bots"})));
}
// Only BotFather can register bots
// Require botfather_token field matching the stored BotFather token
if let Some(ref bf_token) = req.botfather_token {
let botfather_fp = "0000000000000000botfather00000000";
let bf_key = format!("bot_fp:{}", botfather_fp);
let stored_token = state.db.tokens.get(bf_key.as_bytes())
.ok().flatten()
.map(|v| String::from_utf8_lossy(&v).to_string());
if stored_token.as_deref() != Some(bf_token.as_str()) {
return Ok(Json(serde_json::json!({"ok": false, "description": "invalid BotFather token"})));
}
} else {
return Ok(Json(serde_json::json!({"ok": false, "description": "bot registration requires BotFather authorization. Message @botfather to create a bot."})));
}
let fp = req
.fingerprint
.chars()

View File

@@ -50,7 +50,7 @@ async fn pwa_manifest() -> impl IntoResponse {
async fn service_worker() -> impl IntoResponse {
([(header::CONTENT_TYPE, "application/javascript")], r##"
const CACHE = 'wz-v9';
const CACHE = 'wz-v10';
const SHELL = ['/', '/wasm/warzone_wasm.js', '/wasm/warzone_wasm_bg.wasm', '/icon.svg', '/manifest.json'];
self.addEventListener('install', e => {
@@ -241,7 +241,7 @@ let pollTimer = null;
let ws = null; // WebSocket connection
let wasmReady = false;
const VERSION = '0.0.27';
const VERSION = '0.0.28';
let DEBUG = true; // toggle with /debug command
// ── Receipt tracking ──

View File

@@ -32,6 +32,13 @@ chmod +x /home/warzone/warzone-server /home/warzone/warzone-client
cp "federation-${HOSTNAME}.json" /home/warzone/federation.json
chown warzone:warzone /home/warzone/warzone-server /home/warzone/warzone-client /home/warzone/federation.json
# Copy environment file
if [ -f "warzone-server.env.${HOSTNAME}" ]; then
cp "warzone-server.env.${HOSTNAME}" /home/warzone/server.env
chown warzone:warzone /home/warzone/server.env
echo " Environment: $(cat /home/warzone/server.env | grep -v '^#' | grep .)"
fi
# Install systemd service + journald log cap
echo "[4/5] Installing systemd service..."
cp warzone-server.service /etc/systemd/system/

View File

@@ -0,0 +1,2 @@
# kh3rad3ree: federation + bots enabled
EXTRA_ARGS=--enable-bots

View File

@@ -0,0 +1,2 @@
# mequ: federation only, no bots
EXTRA_ARGS=

View File

@@ -8,7 +8,8 @@ Type=simple
User=warzone
Group=warzone
WorkingDirectory=/home/warzone
ExecStart=/home/warzone/warzone-server --bind 0.0.0.0:7700 --data-dir /home/warzone/data --federation /home/warzone/federation.json
EnvironmentFile=-/home/warzone/server.env
ExecStart=/home/warzone/warzone-server --bind 0.0.0.0:7700 --data-dir /home/warzone/data --federation /home/warzone/federation.json $EXTRA_ARGS
Restart=always
RestartSec=3
LimitNOFILE=65536

View File

@@ -4,37 +4,45 @@
featherChat exposes a **Telegram Bot API-compatible** HTTP interface, allowing
developers to build bots that interact with featherChat users using familiar
patterns. Bots register with the server, receive a token, and communicate via
long-polling (webhook support is planned).
patterns. Bots are created exclusively through **@botfather**, receive a token,
and communicate via long-polling or webhooks.
Key properties of v1:
The server must be started with `--enable-bots` to activate bot functionality.
Key properties:
- **BotFather is required** -- only `@botfather` can register bots. It is
auto-created on first server start (token printed in server logs).
- Bot aliases **must** end with `Bot`, `bot`, or `_bot` (auto-enforced on
registration).
- Bots receive encrypted user messages as **base64 blobs** (`raw_encrypted`
field). Plaintext bot-to-bot messages are delivered with a readable `text`
field.
- Bot-sent messages are **plaintext** (not E2E encrypted) in v1.
- `chat_id` values are hex fingerprints (not numeric Telegram-style IDs).
field) unless registered as E2E bots. Plaintext bot-to-bot messages are
delivered with a readable `text` field.
- Bot-sent messages are **plaintext** (not E2E encrypted) unless the bot is
registered in E2E mode.
- `chat_id` accepts both hex fingerprints and numeric IDs (Telegram
compatibility). Numeric IDs are also returned in `from.id`.
- Each bot has an `owner` field linking to the creating user's fingerprint.
---
## Quick Start
```
1. Register your bot:
1. Message @botfather to create a bot (or use BotFather token from server logs).
BotFather registers the bot via:
POST /v1/bot/register
{"name": "WeatherBot", "fingerprint": "aabbccdd..."}
{"name": "WeatherBot", "fingerprint": "aabbccdd...", "botfather_token": "<bf_token>"}
2. Extract the token from the response.
3. Poll for updates:
POST /v1/bot/<token>/getUpdates
{"timeout": 5}
{"timeout": 50}
4. Send a reply:
POST /v1/bot/<token>/sendMessage
{"chat_id": "<sender_fingerprint>", "text": "Hello!"}
{"chat_id": "<sender_fingerprint_or_numeric_id>", "text": "Hello!"}
```
---
@@ -48,21 +56,34 @@ POST /v1/bot/register
```
Creates a new bot, stores it in the server database, and auto-registers an
alias.
alias. **Only @botfather can call this endpoint** -- a valid `botfather_token`
is required.
**Request:**
```json
{
"name": "MyBot",
"fingerprint": "aabbccdd1122334455667788aabbccdd"
"fingerprint": "aabbccdd1122334455667788aabbccdd",
"botfather_token": "<botfather_token>",
"owner": "<creator_fingerprint>"
}
```
| Field | Type | Description |
|---------------|--------|----------------------------------------------|
|--------------------|--------|---------------------------------------------------|
| `name` | string | Display name. Alias suffix auto-added if needed. |
| `fingerprint` | string | Hex-encoded public key fingerprint for the bot. |
| `botfather_token` | string | BotFather authorization token (required). |
| `owner` | string | Fingerprint of the user who requested creation. |
**E2E bot registration** (optional additional fields):
| Field | Type | Description |
|---------------|--------|--------------------------------------------------|
| `e2e` | bool | Set to `true` to register as an E2E bot. |
| `bundle` | object | Full prekey bundle (identity_key, signed_prekey, signature, one_time_prekeys). |
| `eth_address` | string | Ethereum address for the bot. |
**Response:**
@@ -73,7 +94,8 @@ alias.
"token": "aabbccdd11223344:9f8e7d6c5b4a39281706abcdef012345",
"name": "MyBot",
"fingerprint": "aabbccdd1122334455667788aabbccdd",
"alias": "@mybot_bot"
"alias": "@mybot_bot",
"owner": "<creator_fingerprint>"
}
}
```
@@ -140,13 +162,16 @@ Returns queued messages for the bot and deletes them from the queue.
```
| Field | Type | Description |
|-----------|------|-----------------------------------------------------|
| `timeout` | u64 | Optional. Long-poll wait in seconds. **Capped at 5.** |
|-----------|------|------------------------------------------------------|
| `timeout` | u64 | Optional. Long-poll wait in seconds. **Capped at 50.** |
If the queue is empty and `timeout > 0`, the server waits up to `timeout`
seconds (max 5) before returning an empty result, giving new messages a chance
seconds (max 50) before returning an empty result, giving new messages a chance
to arrive.
> **Note:** If a webhook is configured via `setWebhook`, updates are delivered
> live to the webhook URL via POST instead of being queued for polling.
**Response:**
```json
@@ -278,12 +303,14 @@ Sends a **plaintext** message to a user or another bot.
```
| Field | Type | Description |
|-----------|--------|--------------------------------------------------|
| `chat_id` | string | Recipient fingerprint (hex) or Ethereum address. |
| `text` | string | Plaintext message body. |
|--------------|--------|-----------------------------------------------------------|
| `chat_id` | string/int | Recipient fingerprint (hex), Ethereum address, or numeric ID. |
| `text` | string | Message body. |
| `parse_mode` | string | Optional. `"HTML"` renders basic tags (<b>, <i>, <code>, <a>). |
Non-hex characters in `chat_id` are stripped and the value is lowercased before
routing.
`chat_id` accepts hex fingerprint strings, Ethereum addresses, or numeric
integer IDs (Telegram compatibility). Non-hex characters in string chat_ids are
stripped and the value is lowercased before routing.
**Response:**
@@ -323,13 +350,15 @@ WebSocket connection (`true`) or queued for later retrieval (`false`).
| Feature | Telegram | featherChat |
|---------|----------|-------------|
| `chat_id` type | Numeric integer | Hex fingerprint string |
| `getUpdates` timeout | Up to 50s | Capped at **5s** |
| Message content | Always plaintext | Encrypted messages arrive as `raw_encrypted` base64; bot must decrypt if it has a session |
| Bot-sent messages | Plaintext | Plaintext (not E2E encrypted) in v1 |
| Inline keyboards / callback queries | Supported | Not yet (planned) |
| `chat_id` type | Numeric integer | Hex fingerprint string or numeric integer (both accepted) |
| `getUpdates` timeout | Up to 50s | Capped at **50s** |
| Message content | Always plaintext | Encrypted messages arrive as `raw_encrypted` base64; E2E bots can decrypt |
| Bot-sent messages | Plaintext | Plaintext by default; E2E mode available |
| `from.id` | Numeric integer | Numeric integer (`from.id_str` has hex fingerprint) |
| `parse_mode` | Renders HTML/Markdown | HTML rendered (<b>, <i>, <code>, <a>) |
| Inline keyboards / callback queries | Supported | Stored + delivered, no popup |
| Webhooks (`setWebhook`) | Supported | Implemented -- updates delivered live to webhook URL |
| Media groups | Supported | Not yet (planned) |
| Webhooks (`setWebhook`) | Supported | Not yet (planned) |
| File download (`getFile`) | Supported | Not yet (planned) |
---
@@ -344,7 +373,7 @@ TOKEN = "your_bot_token"
API = f"http://localhost:7700/v1/bot/{TOKEN}"
while True:
resp = requests.post(f"{API}/getUpdates", json={"timeout": 5}).json()
resp = requests.post(f"{API}/getUpdates", json={"timeout": 50}).json()
for update in resp.get("result", []):
msg = update.get("message", {})
text = msg.get("text") or "[encrypted]"
@@ -392,10 +421,20 @@ like a password.**
---
## Bot Bridge (`tools/bot-bridge.py`)
A compatibility layer for existing Telegram bot libraries. Translates between
featherChat Bot API and standard TG libraries (python-telegram-bot, aiogram,
Telegraf). Handles differences like fingerprint-based chat_id, numeric ID
translation, and webhook forwarding.
```bash
python tools/bot-bridge.py --token YOUR_BOT_TOKEN --server http://localhost:7700
```
---
## Future Plans
- **Webhook mode** (`setWebhook`) -- push updates to a URL instead of polling.
- **Inline keyboards and callback queries** -- interactive message buttons.
- **E2E encrypted bot sessions** -- bots participate in X3DH key exchange.
- **File send/receive APIs** -- `sendDocument`, `getFile`.
- **Group bot support** -- bots in group chats with sender-key encryption.

View File

@@ -5,15 +5,42 @@
Server: `http://HOST:7700`
All bot endpoints: `/v1/bot/<TOKEN>/METHOD`
Register bot:
**Prerequisites:** The server must be started with `--enable-bots` to activate bot functionality.
### BotFather Registration
Bots can only be created through `@botfather`. On first server start, BotFather is auto-created and its token is printed in the server logs.
To create a bot:
1. Message `@botfather` in the chat client (or use the BotFather token from server logs for programmatic access).
2. BotFather calls `/v1/bot/register` with your request, including a `botfather_token` field for authorization.
Registration request (sent by BotFather internally):
```
POST /v1/bot/register
{"name":"MyBot","fingerprint":"any_32_hex_chars"}
→ {"ok":true,"result":{"token":"TOKEN","alias":"@mybot_bot"}}
{"name":"MyBot","fingerprint":"any_32_hex_chars","botfather_token":"<bf_token>"}
→ {"ok":true,"result":{"token":"TOKEN","alias":"@mybot_bot","owner":"<creator_fp>"}}
```
Bot names must end with Bot/bot/_bot. Token format: `<fp_prefix>:<random_hex>`.
### E2E Bot Mode
Bots can optionally participate in E2E encryption. Pass additional fields during registration:
```json
{
"name": "SecureBot",
"fingerprint": "...",
"botfather_token": "...",
"e2e": true,
"bundle": { "identity_key": "...", "signed_prekey": "...", "signature": "...", "one_time_prekeys": ["..."] },
"eth_address": "0x..."
}
```
An E2E bot registers a full prekey bundle and can establish X3DH sessions with users, receiving decryptable messages instead of `raw_encrypted` blobs.
## Endpoints
### getMe
@@ -190,25 +217,41 @@ poll();
| Feature | Telegram | featherChat |
|---------|----------|------------|
| chat_id | numeric | hex fingerprint string |
| getUpdates timeout | up to 50s | up to 30s |
| User messages | plaintext | E2E encrypted (text=null in v1) |
| Bot messages | plaintext | plaintext (no E2E) |
| chat_id | numeric | hex fingerprint string OR numeric (both accepted) |
| getUpdates timeout | up to 50s | up to 50s |
| User messages | plaintext | E2E encrypted (text=null unless E2E bot) |
| Bot messages | plaintext | plaintext (no E2E) unless E2E bot mode |
| File upload | multipart form | JSON reference (v1) |
| Inline keyboards | full support | stored + delivered, no popup |
| Callback queries | full popup | acknowledged, no popup |
| Webhooks | full HTTPS | URL stored, delivery planned |
| Webhooks | full HTTPS | URL stored, updates delivered live (POST to webhook URL) |
| Media groups | supported | not yet |
| parse_mode | renders HTML/MD | stored, not rendered (v1) |
| parse_mode | renders HTML/MD | HTML rendered (<b>, <i>, <code>, <a>) |
## Key Patterns
**Always use offset** — without it, the same messages are returned every poll.
**chat_id is the sender's fingerprint** — use `msg.chat.id` or `msg.from.id`.
**chat_id is the sender's fingerprint** — use `msg.chat.id` or `msg.from.id`. Note: `from.id` is now a numeric integer for TG compatibility; use `from.id_str` for the hex fingerprint.
**Bot alias** — users message bots via `@mybot_bot` which resolves to the bot's fingerprint.
**Error handling** — all responses have `{"ok": bool}`. Check `ok` before accessing `result`.
**Rate limits** — 200 concurrent server requests, no per-bot limit (be reasonable).
## Bot Bridge (`tools/bot-bridge.py`)
The bot bridge provides a compatibility layer for existing Telegram bot libraries. It translates between featherChat's Bot API and standard TG libraries.
**Supported libraries:**
- **python-telegram-bot** — set `base_url` to `http://your-server:7700/v1/bot/`
- **aiogram** — configure the bot session with the featherChat server URL
- **Telegraf (Node.js)** — set `telegram.apiRoot` to `http://your-server:7700/v1/bot`
Usage:
```bash
python tools/bot-bridge.py --token YOUR_BOT_TOKEN --server http://localhost:7700
```
The bridge handles differences like fingerprint-based chat_id, numeric ID translation, and webhook forwarding.

View File

@@ -131,21 +131,47 @@ no prekeys available | recipient's one-time prekeys exhausted | they need to re-
## Bot API (Telegram-compatible)
Register: POST /v1/bot/register {"name":"MyBot","fingerprint":"<fp>"}
→ returns token + auto-creates @mybot_bot alias
### BotFather
`@botfather` is the only way to create bots. It is auto-created on first server start (token printed in server logs). Users message `@botfather` to register new bots. The server must be started with `--enable-bots` to activate bot functionality.
### Registration
Bots are created via BotFather, which calls POST /v1/bot/register with a `botfather_token` field. Each bot has an `owner` field linking it to the user who requested creation.
Bot aliases must end with Bot, bot, or _bot. Non-bots cannot use these.
### Plaintext Bot Messaging
Clients auto-detect bot aliases (names ending in Bot/bot/_bot) and send messages unencrypted (plaintext JSON). No E2E session is established for standard bot interactions.
### E2E Bot Option
Bots can optionally participate in E2E encryption by registering with a seed and prekey bundle. Pass `e2e: true` + `bundle` + `eth_address` in the registration request. Users messaging an E2E bot establish a normal X3DH session.
### Bot Bridge
`tools/bot-bridge.py` provides Telegram library compatibility. It translates between featherChat Bot API and standard TG bot libraries (python-telegram-bot, aiogram, Telegraf).
### Endpoints
|Endpoint|Method|Body|
|---|---|---|
|/bot/:token/getMe|GET||
|/bot/:token/getUpdates|POST|{"timeout":5}|
|/bot/:token/sendMessage|POST|{"chat_id":"<fp>","text":"Hello"}|
|/bot/:token/getMe|GET|--|
|/bot/:token/getUpdates|POST|{"timeout":50}|
|/bot/:token/sendMessage|POST|{"chat_id":"<fp_or_numeric>","text":"Hello","parse_mode":"HTML"}|
|/bot/:token/setWebhook|POST|{"url":"https://..."}|
|/bot/:token/deleteWebhook|POST|--|
|/bot/:token/getWebhookInfo|GET|--|
- Token format: fp_prefix:random_hex
- getUpdates: long-poll (max 5s), returns then deletes queued msgs
- sendMessage: plaintext JSON, NOT E2E encrypted
- getUpdates: long-poll (max 50s), returns then deletes queued msgs
- sendMessage: plaintext JSON, NOT E2E encrypted (unless E2E bot)
- Bot msgs delivered via same routing (WS push or DB queue)
- Webhooks: updates are delivered live to the registered URL (POST with JSON body)
- chat_id: accepts hex fingerprint or numeric ID (TG compatibility)
- parse_mode: `HTML` renders basic HTML tags (<b>, <i>, <code>, <a>) in clients
- from.id is numeric (integer), from.id_str contains the hex fingerprint
Update types in getUpdates:
- Encrypted msg: text=null, raw_encrypted=base64
@@ -153,15 +179,13 @@ Update types in getUpdates:
- Call signal: text="/call_Offer", call_signal={type,payload}
- File: document={file_name,file_size}
v1 limits: sendMessage is plaintext (no E2E), timeout max 5s, no webhooks yet.
Echo bot (Python):
```python
import requests, time
TOKEN = "your_token"
API = f"http://srv:7700/v1/bot/{TOKEN}"
while True:
for u in requests.post(f"{API}/getUpdates",json={"timeout":5}).json().get("result",[]):
for u in requests.post(f"{API}/getUpdates",json={"timeout":50}).json().get("result",[]):
m = u["message"]
if m.get("text"): requests.post(f"{API}/sendMessage",json={"chat_id":m["chat"]["id"],"text":"Echo: "+m["text"]})
time.sleep(1)

View File

@@ -67,6 +67,7 @@ Rust 1.75 or later (`rust-version = "1.75"` in `Cargo.toml`).
| `--bind` | `-b` | `0.0.0.0:7700` | Address and port to listen on |
| `--data-dir` | `-d` | `./warzone-data` | Directory for the sled database |
| `--federation` | `-f` | *(none)* | Path to federation JSON config file |
| `--enable-bots` | | *(off)* | Enable Bot API and auto-create BotFather on startup |
### Environment Variables
@@ -75,6 +76,20 @@ Rust 1.75 or later (`rust-version = "1.75"` in `Cargo.toml`).
| `RUST_LOG` | `warn` (production) | Log filter. Examples: `info`, `warzone_server=debug`, `trace` |
| `WZP_RELAY_ADDR` | *(none)* | WZP voice relay address advertised to clients |
### Per-Instance Configuration (`server.env`)
Each server instance can use a `server.env` file for per-instance settings.
Place it in the working directory or alongside the binary. This allows
different instances to have different configurations (e.g., bots enabled on
one server but not another).
Example `server.env`:
```
RUST_LOG=info
WZP_RELAY_ADDR=relay.example.com:3478
ENABLE_BOTS=true
```
### systemd Service
A production-ready unit file is provided at `deploy/warzone-server.service`:
@@ -209,6 +224,42 @@ Returns JSON with connection state, peer info, and presence data.
---
## 4b. Bot System
### Enabling Bots
Start the server with `--enable-bots` to activate bot functionality. Without
this flag, all bot endpoints return 403.
```bash
./warzone-server --bind 0.0.0.0:7700 --enable-bots
```
### BotFather Auto-Creation
On first start with `--enable-bots`, the server auto-creates the `@botfather`
bot. The BotFather token is printed to the server logs. Users interact with
`@botfather` to register new bots.
### Per-Instance Bot Toggle
Bot support can be enabled independently per server instance:
| Instance | Bots | Config |
|----------|------|--------|
| mequ | Disabled | No `--enable-bots` flag |
| kh3rad3ree | Enabled | `--enable-bots` flag set |
### Bot Webhook Delivery
When a bot has a webhook configured (via `setWebhook`), incoming messages are
delivered live to the webhook URL via HTTP POST instead of being queued for
`getUpdates` polling. This is integrated into the standard message routing
pipeline -- `deliver_or_queue` checks for webhook configuration before
queueing.
---
## 5. API Reference
All endpoints are prefixed with `/v1`. The web UI is served at `/`.

View File

@@ -56,9 +56,10 @@ warzone-server --bind 0.0.0.0:7700 --data-dir ./warzone-data
```
| Flag | Default | Description |
|--------------|------------------|--------------------|
|-----------------|------------------|--------------------------------------|
| `--bind` | `0.0.0.0:7700` | Listen address |
| `--data-dir` | `./warzone-data` | sled database path |
| `--enable-bots` | *(off)* | Enable Bot API and BotFather |
Environment variables:
@@ -336,6 +337,35 @@ The friend list is encrypted client-side and stored on the server as an opaque b
---
## Bots
### Messaging Bots
Clients auto-detect bot aliases (names ending in `Bot`, `bot`, or `_bot`) and send messages as plaintext -- no E2E session is established. Simply use `/peer @mybot_bot` and type your message. The client handles the rest.
### Creating Bots with BotFather
To create a bot, message `@botfather`:
1. `/peer @botfather`
2. Send a message requesting a new bot (e.g., "create WeatherBot")
3. BotFather registers the bot and returns the API token
4. Use the token to run your bot against the server's Bot API
BotFather is auto-created on servers that have `--enable-bots` enabled. It is the only way to create bots.
### Bot Bridge for Telegram Compatibility
The `tools/bot-bridge.py` script provides a compatibility layer that lets you use existing Telegram bot libraries (python-telegram-bot, aiogram, Telegraf) with featherChat. It translates between the two APIs, handling differences like fingerprint-based addressing and numeric ID translation.
```bash
python tools/bot-bridge.py --token YOUR_BOT_TOKEN --server http://localhost:7700
```
See `docs/BOT_API.md` and `docs/LLM_BOT_DEV.md` for full Bot API documentation.
---
## Federation
Federation connects two featherChat servers so that users on different servers can message each other transparently.