Files
comfy-discord-web/README.md
Khoa (Revenovich) Tran Gia f6907d2c39 docs: update README for current architecture, remove stale docs
Rewrote README.md to reflect the actual project state: dual Discord
bot + FastAPI web UI, WorkflowInspector-based dynamic node injection,
no SerialJobQueue, full env var table, frontend build steps, web auth
setup, and updated credits/troubleshooting.

Removed three files that were actively misleading:
- DEVELOPMENT.md and QUICK_START.md referenced deleted modules
  (job_queue.py, upload.py) and old WorkflowManager/StateManager APIs
- backfill_image_data.py was a completed one-shot migration script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:00:13 +07:00

321 lines
13 KiB
Markdown

# ComfyUI Discord Bot + Web UI
A Discord bot and web interface that integrates with [ComfyUI](https://github.com/comfyanonymous/ComfyUI) to generate AI images and videos. Requests can be submitted through Discord commands or a browser-based UI with real-time progress updates.
## Features
**Discord Bot**
- Image and video generation via simple prompts or full ComfyUI workflows
- Runtime workflow parameter changes (prompt, negative prompt, input images, seeds)
- Preset management — save and recall workflow configurations
- Generation history with full output retrieval
- Server control (start/stop ComfyUI via NSSM service)
- Automatic image compression to fit Discord's 8 MiB limit
**Web UI**
- Invite-token authentication with JWT session cookies
- Simple generate form and full dynamic workflow form (auto-discovers all node inputs)
- Input image library — upload, browse, and select images for generation
- Generation history with image preview
- Preset management
- Real-time status dashboard (ComfyUI connection, queue depth)
- WebSocket-based live progress updates during generation
- Admin panel for token and server management
## Architecture
```
the-third-rev/
├── bot.py # Entry point — Discord bot + Uvicorn run via asyncio.gather
├── config.py # BotConfig dataclass, loads all env vars
├── comfy_client.py # ComfyUI REST + WebSocket client
├── workflow_inspector.py # Dynamic node discovery and override injection
├── workflow_manager.py # Workflow template storage (get/set)
├── workflow_state.py # Runtime override dict with file persistence
├── generation_db.py # SQLite generation history + file BLOBs
├── input_image_db.py # SQLite input image storage
├── token_store.py # SHA-256 hashed invite tokens
├── preset_manager.py # Workflow preset CRUD
├── user_state_registry.py # Per-user workflow state for web sessions
├── image_utils.py # PIL-based image compression
├── media_uploader.py # Optional external media upload
├── status_monitor.py # Background status polling and Discord log channel
├── discord_utils.py # Discord helpers, decorators, argument parsing
├── commands/ # Discord command handlers
│ ├── __init__.py
│ ├── generation.py # generate, workflow-gen
│ ├── workflow.py # workflow-load
│ ├── history.py # history, get-history
│ ├── input_images.py # input image upload/management
│ ├── presets.py # preset save/load/delete
│ ├── server.py # ComfyUI server control
│ ├── utility.py # test, info, misc
│ ├── workflow_changes.py # get/set workflow overrides
│ └── help_command.py # custom help
├── web/ # FastAPI application
│ ├── app.py # App factory, middleware, static file serving
│ ├── auth.py # JWT create/verify
│ ├── deps.py # Shared FastAPI dependencies (bot reference)
│ ├── login_guard.py # Auth decorators
│ ├── ws_bus.py # Per-user WebSocket broadcast bus
│ └── routers/ # API endpoints (generate, history, inputs, presets, ...)
└── frontend/ # React + TypeScript + Vite + Tailwind source
└── src/
├── pages/ # GeneratePage, WorkflowPage, HistoryPage, ...
├── components/ # Layout, DynamicWorkflowForm, LazyImage
├── hooks/ # useAuth, useWebSocket, useStatus
└── context/ # GenerationContext (pending count badge)
```
ComfyUI's own queue handles job ordering — no separate job queue exists in this bot. Generation callbacks are matched to requests via a `prompt_id → callback` map in `ComfyClient`.
## Requirements
- Python 3.10+
- Node.js 18+ (for building the frontend)
- ComfyUI running and accessible
- Discord bot token with **Message Content Intent** enabled
**Python dependencies:**
```bash
pip install discord.py aiohttp websockets python-dotenv fastapi uvicorn pillow
```
## Installation
### 1. Clone and install Python dependencies
```bash
git clone <repo-url>
cd the-third-rev
pip install discord.py aiohttp websockets python-dotenv fastapi uvicorn pillow
```
### 2. Build the frontend
```bash
cd frontend
npm install
npm run build
cd ..
```
The build output lands in `web-static/` and is served automatically by FastAPI.
### 3. Configure environment
Create a `.env` file in the project root:
```bash
# ── Required ────────────────────────────────────────
DISCORD_BOT_TOKEN=your_discord_bot_token
COMFY_SERVER=localhost:8188
# ── ComfyUI paths ───────────────────────────────────
COMFY_OUTPUT_PATH=C:\path\to\ComfyUI\output
COMFY_INPUT_PATH=C:\path\to\ComfyUI\input
COMFY_HISTORY_LIMIT=10
# ── Startup workflow ────────────────────────────────
WORKFLOW_FILE=workflows/my_workflow.json # optional; loaded at startup
# ── Web UI ──────────────────────────────────────────
WEB_ENABLED=true
WEB_HOST=0.0.0.0
WEB_PORT=8080
WEB_SECRET_KEY=change-me-to-a-random-secret
WEB_JWT_EXPIRE_HOURS=720
WEB_SECURE_COOKIE=false # set true if serving over HTTPS
# ── Admin ───────────────────────────────────────────
ADMIN_PASSWORD=your_admin_password
# ── ComfyUI server control (optional) ───────────────
COMFY_SERVICE_NAME=ComfyUI # NSSM service name
COMFY_START_BAT=C:\path\to\run_nvidia_gpu.bat
COMFY_LOG_DIR=C:\path\to\logs
COMFY_AUTOSTART=false # auto-start ComfyUI on bot launch
# ── Discord status log channel (optional) ────────────
LOG_CHANNEL_ID=123456789012345678
# ── External media upload (optional) ────────────────
MEDIA_UPLOAD_USER=
MEDIA_UPLOAD_PASS=
```
### Full configuration reference
| Variable | Required | Default | Description |
|---|---|---|---|
| `DISCORD_BOT_TOKEN` | Yes | — | Discord bot token |
| `COMFY_SERVER` | Yes | — | ComfyUI address (`host:port`) |
| `COMFY_OUTPUT_PATH` | No | `...\ComfyUI\output` | ComfyUI output directory |
| `COMFY_INPUT_PATH` | No | `...\ComfyUI\input` | ComfyUI input directory |
| `COMFY_HISTORY_LIMIT` | No | `10` | Generations kept in history |
| `WORKFLOW_FILE` | No | — | Workflow JSON to load at startup |
| `WEB_ENABLED` | No | `true` | Enable web UI |
| `WEB_HOST` | No | `0.0.0.0` | Web server bind address |
| `WEB_PORT` | No | `8080` | Web server port |
| `WEB_SECRET_KEY` | No | — | JWT signing secret (set in production) |
| `WEB_JWT_EXPIRE_HOURS` | No | `720` | Session expiry in hours |
| `WEB_SECURE_COOKIE` | No | `false` | Mark session cookie as Secure (HTTPS only) |
| `WEB_TOKEN_FILE` | No | `invite_tokens.json` | Invite token storage path |
| `ADMIN_PASSWORD` | No | — | Admin panel password |
| `COMFY_SERVICE_NAME` | No | — | NSSM service name for server control |
| `COMFY_START_BAT` | No | — | ComfyUI launch script path |
| `COMFY_LOG_DIR` | No | — | Directory for ComfyUI logs |
| `COMFY_AUTOSTART` | No | `false` | Auto-start ComfyUI on bot launch |
| `LOG_CHANNEL_ID` | No | — | Discord channel ID for status messages |
### 4. Create a web UI invite token
The web UI requires an invite token to register an account:
```bash
python -c "from token_store import create_token; print(create_token('username'))"
```
Copy the printed token — it is shown only once. Give it to the user who will register.
### 5. Run
```bash
python bot.py
```
The bot starts the Discord client and the web server concurrently. Navigate to `http://localhost:8080` to access the web UI.
## Discord Commands
All commands use the `ttr!` prefix.
### Generation
| Command | Alias | Description |
|---|---|---|
| `ttr!generate prompt:<text>` | `ttr!gen` | Generate using prompt mode |
| `ttr!generate prompt:<text> negative_prompt:<text>` | | Generate with negative prompt |
| `ttr!workflow-gen` | `ttr!wfg` | Execute loaded workflow with current overrides |
| `ttr!workflow-gen queue:5` | | Queue 5 workflow runs |
### Workflow management
| Command | Alias | Description |
|---|---|---|
| `ttr!workflow-load <path>` | `ttr!wfl` | Load workflow from file path |
| `ttr!workflow-load` (+ attachment) | | Load workflow from attached JSON |
| `ttr!get-current-workflow-changes type:all` | `ttr!gcwc` | Show current overrides |
| `ttr!set-current-workflow-changes type:prompt <text>` | `ttr!scwc` | Set prompt override |
| `ttr!set-current-workflow-changes type:negative_prompt <text>` | | Set negative prompt |
### History
| Command | Alias | Description |
|---|---|---|
| `ttr!history` | | List recent generations |
| `ttr!get-history <id>` | `ttr!gh` | Retrieve output from a past generation |
### Presets
| Command | Description |
|---|---|
| `ttr!preset-save <name>` | Save current workflow overrides as a preset |
| `ttr!preset-load <name>` | Apply a saved preset |
| `ttr!preset-list` | List all presets |
| `ttr!preset-delete <name>` | Delete a preset |
### Server control
| Command | Description |
|---|---|
| `ttr!server-start` | Start the ComfyUI NSSM service |
| `ttr!server-stop` | Stop the ComfyUI NSSM service |
| `ttr!server-status` | Show ComfyUI service status |
| `ttr!server-log` | Tail the ComfyUI log file |
### Utility
| Command | Description |
|---|---|
| `ttr!test` | Verify bot is online |
| `ttr!help` | Show command list |
## Workflow System
### How node injection works
`workflow_inspector.py` dynamically discovers all controllable inputs in any workflow:
- **Prompt** — `CLIPTextEncode` node with title containing "Positive Prompt"
- **Negative prompt** — `CLIPTextEncode` node with title containing "Negative Prompt"
- **Input image** — `LoadImage` nodes (first one = `input_image` key; additional ones get slugified title keys)
- **Seed** — any node with `inputs.seed` or `inputs.noise_seed` (auto-randomized unless explicitly set)
- **Steps, CFG, checkpoint, LoRA** — discovered and injectable via the web workflow form
No hardcoded node IDs. Workflows only need to follow standard ComfyUI node title conventions.
### Workflow overrides persist across restarts
Runtime changes are saved to `current-workflow-changes.json` automatically and restored on startup.
### Loading a custom workflow
1. Design and export your workflow in ComfyUI (Save → API Format)
2. Load it in Discord: `ttr!workflow-load path/to/workflow.json`
or via the web UI: Workflow page → Upload
3. Set overrides and run: `ttr!workflow-gen` or use the web Generate/Workflow page
## Development
### Frontend development
```bash
cd frontend
npm run dev # HMR dev server on :5173, proxies /api + /ws to :8080
```
For production, rebuild with `npm run build`.
### Adding a Discord command
1. Add your handler to the appropriate module in `commands/` (or create a new one)
2. Register it in `commands/__init__.py``register_all_commands()`
3. Use `@require_comfy_client` from `discord_utils.py` if the command needs `bot.comfy`
See `CLAUDE.md` for full architectural details.
### Adding a web API endpoint
1. Create a router in `web/routers/`
2. Register it in `web/app.py` via `app.include_router()`
3. Use `require_auth` / `require_admin` from `web/auth.py` for protected routes
## Troubleshooting
**Web UI shows a blank page in production**
Windows may serve `.js` files as `text/plain`. This is fixed in `web/app.py` with explicit MIME type registration — ensure you are running the latest version.
**ComfyUI connection refused**
Check `COMFY_SERVER` in `.env` and confirm ComfyUI is running. Test with `curl http://localhost:8188`.
**Commands not responding**
Ensure the bot has **Message Content Intent** enabled in the Discord Developer Portal and has sufficient channel permissions.
**Videos not delivered**
Set `COMFY_OUTPUT_PATH` to the correct ComfyUI output directory. The bot reads video files directly from disk.
**Web UI WebSocket disconnects immediately**
Set a proper `WEB_SECRET_KEY` — an empty secret causes JWT validation failures.
## Credits
Built with:
- [discord.py](https://github.com/Rapptz/discord.py) — Discord API
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI) — AI image/video generation backend
- [FastAPI](https://fastapi.tiangolo.com/) — Web API framework
- [Uvicorn](https://www.uvicorn.org/) — ASGI server
- [React](https://react.dev/) + [Vite](https://vitejs.dev/) + [Tailwind CSS](https://tailwindcss.com/) — Web frontend
- [aiohttp](https://github.com/aio-libs/aiohttp) — Async HTTP client
- [Pillow](https://python-pillow.org/) — Image compression