https://github.com/cryptojones/1812
https://github.com/cryptojones/1812
Last synced: 7 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/cryptojones/1812
- Owner: CryptoJones
- License: other
- Created: 2026-05-15T02:09:22.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-05-15T03:52:41.000Z (about 1 month ago)
- Last Synced: 2026-05-15T05:45:04.927Z (about 1 month ago)
- Language: Python
- Size: 21.5 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 1812
**A self-hosted Discord chatbot with configurable LLM backends, persistent memory, and a FastAPI dashboard.**
[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/CryptoJones/1812)
[](https://www.python.org/)
[](https://discordpy.readthedocs.io/)
[]()
> *"Cannons firing. Bells ringing. The overture begins."*
> — Tchaikovsky, 1880
---
## Overview
1812 is a self-hosted, open-source Discord chatbot backed by your choice of LLM. It maintains
per-channel conversation history in SQLite, streams responses token-by-token, supports image input,
and ships with a FastAPI health/dashboard sidecar.
Named after Tchaikovsky's 1812 Overture — a piece that knows exactly when to be quiet
and exactly when to be deafening.
A **CryptoJones** project.
---
## Features
| Feature | Details |
|---|---|
| **Multi-backend LLM** | OpenAI, Anthropic Claude, Ollama (local), OpenRouter |
| **Streaming responses** | Token-by-token output, edited live in Discord |
| **SQLite persistence** | Per-channel history and per-server personas survive restarts |
| **Per-user memory** | Remember facts about individual users across sessions |
| **Per-server personas** | Different personality per Discord server |
| **Slash commands** | `/clear`, `/persona`, `/model`, `/remember`, `/forget` |
| **Image input** | Attach images — vision-capable models process them inline |
| **Rate limiting** | Per-user sliding window (configurable requests/window) |
| **Auto-summarisation** | History is summarised by the LLM when it gets too long |
| **FastAPI sidecar** | `/health`, `/api/channels`, `/api/history/:id`, and a live dashboard |
| **JSON structured logging** | Machine-readable logs with level, timestamp, and context |
| **Docker** | Single-container deploy via `docker-compose up` |
| **Graceful shutdown** | SIGTERM/SIGINT handled cleanly |
---
## Architecture
| Component | Technology |
|---|---|
| Bot framework | [discord.py](https://discordpy.readthedocs.io/) 2.3+ |
| LLM backends | OpenAI / Anthropic / Ollama / OpenRouter |
| History storage | SQLite via `aiosqlite` |
| Config | Pydantic Settings + `.env` |
| Web sidecar | FastAPI + uvicorn (background thread) |
| Container | Docker + Docker Compose |
| Tests | pytest + pytest-asyncio |
---
## Quick Start
**Docker (recommended)**
```bash
cp .env.example .env
# Edit .env with your tokens
docker compose up -d
```
**Manual**
```bash
chmod +x setup.sh && ./setup.sh
cp .env.example .env
# Edit .env with your tokens
source .venv/bin/activate
python bot.py
```
---
## Configuration
| Variable | Required | Default | Description |
|---|---|---|---|
| `DISCORD_TOKEN` | Yes | — | Your Discord bot token |
| `LLM_PROVIDER` | No | `openai` | `openai` \| `anthropic` \| `ollama` \| `openrouter` |
| `LLM_MODEL` | No | `gpt-4o-mini` | Model name for the selected provider |
| `OPENAI_API_KEY` | If OpenAI | — | OpenAI API key |
| `ANTHROPIC_API_KEY` | If Anthropic | — | Anthropic API key |
| `OPENROUTER_API_KEY` | If OpenRouter | — | OpenRouter API key |
| `OLLAMA_BASE_URL` | No | `http://localhost:11434/v1` | Ollama endpoint |
| `SYSTEM_PROMPT` | No | `You are 1812...` | Default bot personality |
| `MAX_HISTORY_MESSAGES` | No | `20` | Messages to keep per channel before summarising |
| `SUMMARISE_AT` | No | `40` | History length that triggers summarisation |
| `RATE_LIMIT_REQUESTS` | No | `10` | Max requests per user per window |
| `RATE_LIMIT_WINDOW_SECONDS` | No | `60` | Rate limit sliding window |
| `DB_PATH` | No | `1812.db` | Path to SQLite database file |
| `WEB_HOST` | No | `0.0.0.0` | FastAPI sidecar host |
| `WEB_PORT` | No | `8080` | FastAPI sidecar port |
| `SHUTDOWN_AFTER_MINUTES` | No | unset (= unbounded) | Auto-shutdown timer in minutes. CLI `--shutdown-after N` overrides this. |
---
## CLI Flags
| Flag | Description |
|---|---|
| `--shutdown-after N` | Self-shutdown after N minutes of runtime. Overrides `SHUTDOWN_AFTER_MINUTES`. `0` is an explicit "unbounded" sentinel that clears any env value. Useful for time-boxed runs, cron jobs, and CI canaries. |
```bash
# Run for exactly two hours, then graceful shutdown.
python bot.py --shutdown-after 120
# Wipe an env-configured timer for this invocation only.
SHUTDOWN_AFTER_MINUTES=30 python bot.py --shutdown-after 0
```
---
## Slash Commands
| Command | Who | Description |
|---|---|---|
| `/clear` | Anyone | Wipe conversation history for the current channel |
| `/persona ` | Anyone | Switch persona: `default`, `concise`, `creative`, `technical` |
| `/model ` | Admin only | Change the LLM model at runtime |
| `/remember ` | Anyone | Save a personal note about yourself for the bot to use |
| `/forget` | Anyone | Clear your personal memory |
---
## Discord Setup
1. Go to [discord.com/developers/applications](https://discord.com/developers/applications)
2. Create or select your application
3. Navigate to **Bot** → enable **Message Content Intent** and **Server Members Intent**
4. Copy your bot token into `.env`
5. Invite via **OAuth2 → URL Generator** — scopes: `bot`, `applications.commands` — permissions: `Send Messages`, `Read Message History`, `Attach Files`
---
## Web Dashboard
The FastAPI sidecar runs on port 8080 by default:
| Endpoint | Description |
|---|---|
| `GET /health` | Liveness check |
| `GET /api/channels` | List all channels with history |
| `GET /api/history/{channel_id}` | Full message history for a channel |
| `GET /` | Live HTML dashboard |
---
## Project Structure
```
1812/
├── bot.py # Discord bot, slash commands, streaming
├── config.py # Pydantic Settings
├── db.py # SQLite helpers (aiosqlite)
├── llm.py # LLM backend abstraction (OpenAI / Anthropic / Ollama / OpenRouter)
├── rate_limiter.py # Per-user sliding window rate limiter
├── web.py # FastAPI sidecar
├── tests/ # pytest test suite
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── setup.sh
└── .env.example
```
---
## Running Tests
```bash
python3 -m pytest tests/ -v
```
31 tests covering rate limiting, database operations, LLM backend selection, and bot helpers.
---
## Contributing
Pull requests welcome. Keep it simple. Keep it clean. Write tests first.
---
## License
**Apache License 2.0** — Copyright 2026 Aaron K. Clark. See [LICENSE](LICENSE).
---
## Acknowledgments
To **Dr. John Crichton** of the Farscape Project — astronaut, wormhole theorist, and the most
unlikely hero to ever fall through the wrong end of the universe. Wherever he is.
---
Proudly Made in Nebraska. 🌽