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>
197 lines
4.5 KiB
Markdown
197 lines
4.5 KiB
Markdown
# 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.
|