Spaces:
Running
Running
SilverElixir commited on
Add files via upload
Browse files
README.md
CHANGED
|
@@ -13,25 +13,25 @@ A Telegram bot built to match Claude's tone and capabilities as closely as possi
|
|
| 13 |
|
| 14 |
**Stack:** Python 3.13 · aiogram · FastAPI · google-genai · Docker
|
| 15 |
|
| 16 |
-
> The YAML block above is Hugging Face Space metadata, not a mistake
|
| 17 |
|
| 18 |
## Features
|
| 19 |
|
| 20 |
-
- **Automatic model routing**
|
| 21 |
-
- **Streaming replies** with a self-calibrating typing-speed pacer, so answers
|
| 22 |
-
- **
|
| 23 |
-
- **TikTok
|
| 24 |
-
- **Image generation**
|
| 25 |
-
- **Text-to-speech**
|
| 26 |
-
- `/draw` and `/tts` also work as plain phrases at the start of a message ("draw a cat
|
| 27 |
-
- **Persistent state**
|
| 28 |
-
- **Error tracking**
|
| 29 |
|
| 30 |
## How it works
|
| 31 |
|
| 32 |
-
Lumen is a single FastAPI + aiogram service. Telegram delivers updates to a webhook
|
| 33 |
|
| 34 |
-
The codebase is a modular monolith
|
| 35 |
|
| 36 |
See **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for a deeper look at routing, streaming, the security layers, and the TikTok downloader.
|
| 37 |
|
|
@@ -50,11 +50,11 @@ See **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for a deeper look at routin
|
|
| 50 |
curl -H "Authorization: Bearer <BOT_TOKEN>" https://<space-host>/admin_keys
|
| 51 |
```
|
| 52 |
|
| 53 |
-
Hugging Face Spaces' outbound IPs are blocked by Telegram's API at the network level, so a small proxy is required
|
| 54 |
|
| 55 |
## Configuration
|
| 56 |
|
| 57 |
-
Only `BOT_TOKEN` and `GEMINI_API_KEY` are required
|
| 58 |
|
| 59 |
## Proxy setup
|
| 60 |
|
|
@@ -65,11 +65,11 @@ TELEGRAM_API_BASE_URL=https://<proxy-domain>/fetch/api.telegram.org
|
|
| 65 |
TIKWM_API_BASE_URL=https://<proxy-domain>/fetch/www.tikwm.com
|
| 66 |
```
|
| 67 |
|
| 68 |
-
The proxy only forwards to an explicit host allowlist (`api.telegram.org`, `www.tikwm.com`, `tikwm.com`)
|
| 69 |
|
| 70 |
## Diagnostics
|
| 71 |
|
| 72 |
-
All three endpoints below require `Authorization: Bearer <ADMIN_PANEL_KEY>`:
|
| 73 |
|
| 74 |
| Endpoint | Purpose |
|
| 75 |
|---|---|
|
|
@@ -81,7 +81,7 @@ All three endpoints below require `Authorization: Bearer <ADMIN_PANEL_KEY>`:
|
|
| 81 |
|
| 82 |
## Commands
|
| 83 |
|
| 84 |
-
`/reset`, `/draw`, and `/tts` show up in Telegram's command menu. A few more exist but stay out of the menu on purpose:
|
| 85 |
|
| 86 |
| Command | Access | Purpose |
|
| 87 |
|---|---|---|
|
|
@@ -89,7 +89,7 @@ All three endpoints below require `Authorization: Bearer <ADMIN_PANEL_KEY>`:
|
|
| 89 |
| `/stats` | bot owner, DMs only | Active chat count, process uptime, per-model quota usage. |
|
| 90 |
| `/logs` | bot owner, DMs only | Sends `bot.log` with secrets redacted. |
|
| 91 |
|
| 92 |
-
`/model`, `/provider`, and `/imgmodel` don't exist
|
| 93 |
|
| 94 |
## Testing
|
| 95 |
|
|
@@ -98,13 +98,13 @@ pip install -r requirements.txt -r requirements-dev.txt
|
|
| 98 |
pytest -v
|
| 99 |
```
|
| 100 |
|
| 101 |
-
Test files mirror the module split
|
| 102 |
|
| 103 |
CI (`.github/workflows/ci.yml`) runs `pyflakes` + `pytest` + `pip-audit` on every push and pull request; a successful run triggers `sync-to-hf.yml`, which mirrors the commit to the Hugging Face Space.
|
| 104 |
|
| 105 |
## Known limitations
|
| 106 |
|
| 107 |
-
- Chat history and quota counters survive redeploys only if Upstash is configured (see [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md))
|
| 108 |
-
- YouTube downloading isn't supported
|
| 109 |
- TikTok downloading depends on the unofficial TikWM API, not an official TikTok endpoint, and needs the proxy above to work from Hugging Face Spaces at all.
|
| 110 |
-
- Streaming has only been exercised against mocked clients, not live Gemini/OpenRouter SSE traffic
|
|
|
|
| 13 |
|
| 14 |
**Stack:** Python 3.13 · aiogram · FastAPI · google-genai · Docker
|
| 15 |
|
| 16 |
+
> The YAML block above is Hugging Face Space metadata, not a mistake: this same `README.md` doubles as the Space card. Everything below it is normal GitHub documentation.
|
| 17 |
|
| 18 |
## Features
|
| 19 |
|
| 20 |
+
- **Automatic model routing.** No `/model` command: every message goes to whichever provider actually has what it needs. Web search and link reading always go to Gemini; everything else defaults to free OpenRouter models, protecting Gemini's tight daily quota.
|
| 21 |
+
- **Streaming replies** with a self-calibrating typing-speed pacer, so answers type themselves in instead of landing in a few large chunks.
|
| 22 |
+
- **Defenses against prompt injection and identity leaks.** A deterministic input filter plus output scrubbers keep the bot from revealing which model or provider actually answered.
|
| 23 |
+
- **TikTok downloads** without watermarks: video, slideshows (including "live" photo slides), and original sound.
|
| 24 |
+
- **Image generation** through Pollinations.ai. The model is picked from the prompt itself (anime, fantasy, realism, quick sketch, or a general default).
|
| 25 |
+
- **Text-to-speech**, trying Fish Audio first and falling back to Gemini TTS.
|
| 26 |
+
- `/draw` and `/tts` also work as plain phrases at the start of a message ("draw a cat," "read this out loud"), no slash required.
|
| 27 |
+
- **Persistent state.** An optional Upstash Redis backend keeps chat history and quota counters alive across redeploys.
|
| 28 |
+
- **Error tracking** through an optional Sentry integration that scrubs secrets before sending anything.
|
| 29 |
|
| 30 |
## How it works
|
| 31 |
|
| 32 |
+
Lumen is a single FastAPI + aiogram service. Telegram delivers updates to a webhook. Each message gets routed through a chain of candidate models (Gemini and/or OpenRouter), built on the fly from the message's content: attachments, links, and a couple of lightweight heuristics for "does this need current information" and "is this a heavy request." The first provider that answers wins; the other is tried as a fallback if its whole chain fails.
|
| 33 |
|
| 34 |
+
The codebase is a modular monolith. `bot.py` is the orchestrator; the rest is split into focused modules: `lumen_router_config.py` (model routing), `lumen_formatting.py` (markdown to Telegram HTML), `lumen_security.py` (injection and leak defenses), `lumen_images.py`, `lumen_tts.py`, `lumen_tiktok.py`, `lumen_telegram_transport.py`, `lumen_state_storage.py`, and `lumen_typing_pace.py`.
|
| 35 |
|
| 36 |
See **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for a deeper look at routing, streaming, the security layers, and the TikTok downloader.
|
| 37 |
|
|
|
|
| 50 |
curl -H "Authorization: Bearer <BOT_TOKEN>" https://<space-host>/admin_keys
|
| 51 |
```
|
| 52 |
|
| 53 |
+
Hugging Face Spaces' outbound IPs are blocked by Telegram's API at the network level, so a small proxy is required. See [Proxy setup](#proxy-setup) below.
|
| 54 |
|
| 55 |
## Configuration
|
| 56 |
|
| 57 |
+
Only `BOT_TOKEN` and `GEMINI_API_KEY` are required. Everything else has a sane default; the full reference (proxy addresses, timeouts, storage, rate limiting, TikTok tuning) lives in **[docs/ENVIRONMENT.md](docs/ENVIRONMENT.md)**.
|
| 58 |
|
| 59 |
## Proxy setup
|
| 60 |
|
|
|
|
| 65 |
TIKWM_API_BASE_URL=https://<proxy-domain>/fetch/www.tikwm.com
|
| 66 |
```
|
| 67 |
|
| 68 |
+
The proxy only forwards to an explicit host allowlist (`api.telegram.org`, `www.tikwm.com`, `tikwm.com`). See `proxy.ts` for the implementation and `proxy_test.ts` for its tests.
|
| 69 |
|
| 70 |
## Diagnostics
|
| 71 |
|
| 72 |
+
All three endpoints below require `Authorization: Bearer <ADMIN_PANEL_KEY>` (`/admin_keys`, covered in the deploy steps above, uses `BOT_TOKEN` instead):
|
| 73 |
|
| 74 |
| Endpoint | Purpose |
|
| 75 |
|---|---|
|
|
|
|
| 81 |
|
| 82 |
## Commands
|
| 83 |
|
| 84 |
+
`/start`, `/reset`, `/draw`, and `/tts` show up in Telegram's command menu. A few more exist but stay out of the menu on purpose:
|
| 85 |
|
| 86 |
| Command | Access | Purpose |
|
| 87 |
|---|---|---|
|
|
|
|
| 89 |
| `/stats` | bot owner, DMs only | Active chat count, process uptime, per-model quota usage. |
|
| 90 |
| `/logs` | bot owner, DMs only | Sends `bot.log` with secrets redacted. |
|
| 91 |
|
| 92 |
+
`/model`, `/provider`, and `/imgmodel` don't exist. The router and the image-model picker choose automatically on every request; see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for why.
|
| 93 |
|
| 94 |
## Testing
|
| 95 |
|
|
|
|
| 98 |
pytest -v
|
| 99 |
```
|
| 100 |
|
| 101 |
+
Test files mirror the module split: `test_lumen_formatting.py`, `test_lumen_security.py`, `test_lumen_router_config.py`, and `test_lumen_typing_pace.py` each test their matching module directly, while `test_bot.py` covers everything defined in `bot.py` itself. `conftest.py` stubs `BOT_TOKEN`/`GEMINI_API_KEY`/`BOT_LOG_PATH` so the suite needs no real secrets.
|
| 102 |
|
| 103 |
CI (`.github/workflows/ci.yml`) runs `pyflakes` + `pytest` + `pip-audit` on every push and pull request; a successful run triggers `sync-to-hf.yml`, which mirrors the commit to the Hugging Face Space.
|
| 104 |
|
| 105 |
## Known limitations
|
| 106 |
|
| 107 |
+
- Chat history and quota counters survive redeploys only if Upstash is configured (see [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md)); otherwise they live on the container's ephemeral disk and reset on every rebuild.
|
| 108 |
+
- YouTube downloading isn't supported, because Hugging Face Spaces' outbound IPs are blocked at the TLS handshake level. Viewing and analyzing a video by link still works.
|
| 109 |
- TikTok downloading depends on the unofficial TikWM API, not an official TikTok endpoint, and needs the proxy above to work from Hugging Face Spaces at all.
|
| 110 |
+
- Streaming has only been exercised against mocked clients, not live Gemini/OpenRouter SSE traffic. See the manual smoke-test checklist in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) before touching that code path.
|