Initial commit — ComfyUI Discord bot + web UI
Full source for the-third-rev: Discord bot (discord.py), FastAPI web UI (React/TS/Vite/Tailwind), ComfyUI integration, generation history DB, preset manager, workflow inspector, and all supporting modules. Excluded from tracking: .env, invite_tokens.json, *.db (SQLite), current-workflow-changes.json, user_settings/, presets/, logs/, web-static/ (build output), frontend/node_modules/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
196
QUICK_START.md
Normal file
196
QUICK_START.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# Quick Start Guide
|
||||
|
||||
Quick reference for common development tasks.
|
||||
|
||||
## Add a Simple Command
|
||||
|
||||
```python
|
||||
# commands/your_module.py
|
||||
|
||||
def setup_your_commands(bot, config):
|
||||
@bot.command(name="hello")
|
||||
async def hello(ctx):
|
||||
await ctx.reply("Hello!", mention_author=False)
|
||||
```
|
||||
|
||||
Register it:
|
||||
```python
|
||||
# commands/__init__.py
|
||||
from .your_module import setup_your_commands
|
||||
|
||||
def register_all_commands(bot, config):
|
||||
# ... existing ...
|
||||
setup_your_commands(bot, config)
|
||||
```
|
||||
|
||||
## Add a Command That Uses ComfyUI
|
||||
|
||||
```python
|
||||
from discord_utils import require_comfy_client
|
||||
|
||||
@bot.command(name="my-cmd")
|
||||
@require_comfy_client # Validates bot.comfy exists
|
||||
async def my_cmd(ctx):
|
||||
result = await bot.comfy.some_method()
|
||||
await ctx.reply(f"Result: {result}", mention_author=False)
|
||||
```
|
||||
|
||||
## Add a Long-Running Command
|
||||
|
||||
```python
|
||||
from job_queue import Job
|
||||
|
||||
@bot.command(name="generate")
|
||||
@require_comfy_client
|
||||
async def generate(ctx, *, args: str = ""):
|
||||
async def _run():
|
||||
async with ctx.typing():
|
||||
result = await bot.comfy.generate_image(args)
|
||||
await ctx.reply(f"Done! {result}", mention_author=False)
|
||||
|
||||
pos = await bot.jobq.submit(Job(label="generate", run=_run))
|
||||
await ctx.reply(f"Queued ✅ (position: {pos})", mention_author=False)
|
||||
```
|
||||
|
||||
## Add Configuration
|
||||
|
||||
```python
|
||||
# config.py
|
||||
|
||||
MY_FEATURE_ENABLED = True
|
||||
|
||||
@dataclass
|
||||
class BotConfig:
|
||||
# ... existing fields ...
|
||||
my_feature_enabled: bool = MY_FEATURE_ENABLED
|
||||
|
||||
@classmethod
|
||||
def from_env(cls) -> BotConfig:
|
||||
# ... existing code ...
|
||||
my_feature = os.getenv("MY_FEATURE_ENABLED", "true").lower() == "true"
|
||||
return cls(
|
||||
# ... existing params ...
|
||||
my_feature_enabled=my_feature
|
||||
)
|
||||
```
|
||||
|
||||
Use in commands:
|
||||
```python
|
||||
def setup_my_commands(bot, config):
|
||||
@bot.command(name="feature")
|
||||
async def feature(ctx):
|
||||
if config.my_feature_enabled:
|
||||
await ctx.reply("Enabled!", mention_author=False)
|
||||
```
|
||||
|
||||
## Parse Command Arguments
|
||||
|
||||
```python
|
||||
from discord_utils import parse_labeled_args
|
||||
from config import ARG_PROMPT_KEY, ARG_TYPE_KEY
|
||||
|
||||
@bot.command(name="cmd")
|
||||
async def cmd(ctx, *, args: str = ""):
|
||||
# Parse "prompt:text type:value" format
|
||||
parsed = parse_labeled_args(args, [ARG_PROMPT_KEY, ARG_TYPE_KEY])
|
||||
|
||||
prompt = parsed.get("prompt")
|
||||
img_type = parsed.get("type") or "input" # Default
|
||||
|
||||
if not prompt:
|
||||
await ctx.reply("Missing prompt!", mention_author=False)
|
||||
return
|
||||
```
|
||||
|
||||
## Handle File Uploads
|
||||
|
||||
```python
|
||||
@bot.command(name="upload")
|
||||
async def upload(ctx):
|
||||
if not ctx.message.attachments:
|
||||
await ctx.reply("Attach a file!", mention_author=False)
|
||||
return
|
||||
|
||||
for attachment in ctx.message.attachments:
|
||||
data = await attachment.read()
|
||||
# Process data...
|
||||
```
|
||||
|
||||
## Access Bot State
|
||||
|
||||
```python
|
||||
@bot.command(name="info")
|
||||
async def info(ctx):
|
||||
# Queue size
|
||||
queue_size = await bot.jobq.get_queue_size()
|
||||
|
||||
# Config
|
||||
server = bot.config.comfy_server
|
||||
|
||||
# Last generation
|
||||
last_id = bot.comfy.last_prompt_id
|
||||
|
||||
await ctx.reply(
|
||||
f"Queue: {queue_size}, Server: {server}, Last: {last_id}",
|
||||
mention_author=False
|
||||
)
|
||||
```
|
||||
|
||||
## Add Buttons
|
||||
|
||||
```python
|
||||
from discord.ui import View, Button
|
||||
import discord
|
||||
|
||||
class MyView(View):
|
||||
@discord.ui.button(label="Click", style=discord.ButtonStyle.primary)
|
||||
async def button_callback(self, interaction, button):
|
||||
await interaction.response.send_message("Clicked!", ephemeral=True)
|
||||
|
||||
@bot.command(name="interactive")
|
||||
async def interactive(ctx):
|
||||
await ctx.reply("Press button:", view=MyView(), mention_author=False)
|
||||
```
|
||||
|
||||
## Common Imports
|
||||
|
||||
```python
|
||||
from __future__ import annotations
|
||||
import logging
|
||||
from discord.ext import commands
|
||||
from discord_utils import require_comfy_client
|
||||
from config import ARG_PROMPT_KEY, ARG_TYPE_KEY
|
||||
from job_queue import Job
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
```
|
||||
|
||||
## Test Your Changes
|
||||
|
||||
```bash
|
||||
# Syntax check
|
||||
python -m py_compile commands/your_module.py
|
||||
|
||||
# Run bot
|
||||
python bot.py
|
||||
|
||||
# Test in Discord
|
||||
ttr!your-command
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
commands/
|
||||
├── __init__.py # Register all commands here
|
||||
├── generation.py # Generation commands
|
||||
├── workflow.py # Workflow management
|
||||
├── upload.py # File uploads
|
||||
├── history.py # History retrieval
|
||||
├── workflow_changes.py # State management
|
||||
└── your_module.py # Your new module
|
||||
```
|
||||
|
||||
## Need More Details?
|
||||
|
||||
See `DEVELOPMENT.md` for comprehensive guide with examples, patterns, and best practices.
|
||||
Reference in New Issue
Block a user