Files
Vivi-Speech/.planning/research/QUICK_REFERENCE.md
Dani B 901574f8c8 docs: complete project research (STACK, FEATURES, ARCHITECTURE, PITFALLS, SUMMARY)
Synthesized research findings from 4 parallel researcher agents:

Key Findings:
- Stack: discord.py 2.6.4 + PostgreSQL/SQLite with webhook-driven PluralKit integration
- Architecture: 7-component system with clear separation of concerns, async-native
- Features: Rule-based learning system starting simple, avoiding context inference and ML
- Pitfalls: 8 critical risks identified with phase assignments and prevention strategies

Recommended Approach:
- 5-phase build order (detection → translation → teaching → config → polish)
- Focus on dysgraphia accessibility for teaching interface
- Start with message detection reliability (Phase 1, load-bearing)
- Shared emoji dictionary (Phase 1-3); per-server overrides deferred to Phase 4+

Confidence Levels:
- Tech Stack: VERY HIGH (all production-proven, no experimental choices)
- Architecture: VERY HIGH (mirrors successful production bots)
- Features: HIGH (tight scope, transparent approach)
- Roadmap: HIGH (logical phase progression with value delivery)

Gaps to Address in Requirements:
- Vivi's teaching UX preferences (dysgraphia-specific patterns)
- Exact emoji coverage and naming conventions
- Moderation/teaching permissions model
- Multi-system scope and per-system customization needs

Ready for requirements definition and roadmap creation.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-29 11:02:32 -05:00

352 lines
8.2 KiB
Markdown

# Quick Reference: Tech Stack Decisions
**For comprehensive rationale, see [STACK.md](./STACK.md)**
## One-Page Summary
```
Bot Framework: discord.py 2.6.4 (Python 3.10+)
Database: SQLite (MVP) / PostgreSQL (production)
PluralKit: pluralkit.py + webhook dispatch
Hosting: Railway ($0-5/month) or Oracle Cloud (free)
Command Style: Slash commands (/translate 🎭)
```
---
## Installation Checklist (Fresh Project)
```bash
# Create project
mkdir vivi-speech-translator
cd vivi-speech-translator
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
# Core dependencies
pip install discord.py==2.6.4
pip install pluralkit==1.1.5
pip install aiosqlite==0.19.0 # MVP database
pip install aiohttp==3.9.0 # Webhook server
pip install emoji==2.11.0 # Emoji handling
pip install pydantic==2.5.0 # Data validation
pip install python-dotenv==1.0.0
# Optional (production)
pip install asyncpg==0.29.0 # PostgreSQL driver
pip install sentry-sdk==1.45.0 # Error tracking
# Testing
pip install pytest==7.4.0
pip install pytest-asyncio==0.23.0
```
---
## Database Quick Start
### MVP (SQLite)
```python
import aiosqlite
# Create database
async with aiosqlite.connect('emoji.db') as db:
await db.execute('''
CREATE TABLE IF NOT EXISTS emoji_mappings (
id INTEGER PRIMARY KEY,
emoji TEXT UNIQUE NOT NULL,
meaning TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
await db.commit()
# Use in bot
async def learn_emoji(emoji_str, meaning):
async with aiosqlite.connect('emoji.db') as db:
await db.execute(
'INSERT INTO emoji_mappings (emoji, meaning) VALUES (?, ?)',
(emoji_str, meaning)
)
await db.commit()
```
### Production (PostgreSQL)
```python
import asyncpg
pool = await asyncpg.create_pool('postgresql://user:pwd@host/db')
async def learn_emoji(emoji_str, meaning):
async with pool.acquire() as conn:
await conn.execute(
'INSERT INTO emoji_mappings (emoji, meaning) VALUES ($1, $2)',
emoji_str, meaning
)
```
---
## PluralKit Integration Checklist
- [ ] Get system token: Run `pk;token` in Discord with PluralKit bot
- [ ] Store token in `.env`: `PLURALKIT_TOKEN=pk_...`
- [ ] Create webhook endpoint in your bot
- [ ] Register webhook URL with PluralKit API
- [ ] Set up webhook signature verification (use nacl library)
- [ ] Cache member list in memory on startup
- [ ] Update cache on webhook events (CREATE_MEMBER, UPDATE_MEMBER, DELETE_MEMBER)
**Webhook Endpoint Example:**
```python
from aiohttp import web
async def handle_pk_webhook(request):
body = await request.text()
signature = request.headers.get('X-Signature-Ed25519')
# Verify signature
if not verify_signature(body, signature):
return web.Response(status=401)
data = await request.json()
# Update emoji mappings based on member changes
return web.Response(status=200)
# Add to bot setup
app.router.add_post('/webhooks/pluralkit', handle_pk_webhook)
```
---
## Slash Commands vs Prefix Commands
### ✅ Use Slash Commands (Recommended)
```python
@bot.slash_command(name="learn")
async def learn(ctx, emoji: str, meaning: str):
"""Learn what an emoji means"""
await learn_emoji(emoji, meaning)
await ctx.respond(f"Learned: {emoji} = {meaning}")
# No MessageContent intent needed!
# Users see autocomplete, clearer UI
```
### ❌ Don't Use Prefix Commands
```python
@bot.command(name="learn")
async def learn(ctx, emoji: str, meaning: str):
"""Learn what an emoji means"""
# Requires MessageContent intent ❌
# Harder to use, poor UX
```
---
## Environment Variables (.env)
```bash
# .env (DO NOT COMMIT - add to .gitignore)
DISCORD_TOKEN=your_bot_token_here
PLURALKIT_TOKEN=pk_your_system_token_here
DATABASE_URL=postgresql://user:password@localhost/emojidb
WEBHOOK_SECRET=your_webhook_secret_from_pk
# Optional
SENTRY_DSN=https://...@sentry.io/...
LOG_LEVEL=INFO
```
**Add to .gitignore:**
```
.env
*.db
*.sqlite3
__pycache__/
venv/
```
---
## Bot Intents Configuration
```python
intents = discord.Intents.default()
intents.guilds = True # Required
intents.members = True # For member info
intents.message_content = False # NOT needed (use slash commands)
bot = discord.Bot(intents=intents)
```
**Don't enable message_content unless you parse raw text messages.**
---
## Permissions URL
```
https://discord.com/oauth2/authorize
?client_id=YOUR_CLIENT_ID
&scope=bot
&permissions=536996928
```
**Permissions included:**
- Read Messages/View Channels (1024)
- Send Messages (2048)
- Embed Links (16384)
- Read Message History (65536)
---
## Hosting Setup
### Railway (Recommended)
```bash
# Install Railway CLI
curl -fsSL https://railway.app/install.sh | bash
# Initialize
railway init
# Deploy from GitHub
# (auto-deploys when you push to main)
# View logs
railway logs
# Set environment variables
railway variables set DISCORD_TOKEN=...
```
### Cost
- First $5/month free credit
- $5 for 1GB RAM for bot
- $15 for PostgreSQL (or get free tier)
- **Total: $0-20/month for small bot**
### Oracle Cloud (Free Alternative)
- 4 CPU, 24GB RAM, 200GB storage VM (always free)
- Run bot + PostgreSQL on same VM
- Note: May delete instances after 60 days inactivity
- Requires Linux/Docker knowledge
---
## Common Commands During Development
```bash
# Run locally
python main.py
# Run tests
pytest
# Format code
black .
# Check types
mypy .
# View database (SQLite)
sqlite3 emoji.db
> SELECT * FROM emoji_mappings;
# View logs on Railway
railway logs -f
# Deploy to Railway
git push origin main # auto-deploys
```
---
## Anti-Patterns to Avoid
❌ Using Pycord (py-cord) - unmaintained since 2023
❌ Storing bot token in code - use `.env`
❌ Requesting MessageContent intent for slash commands
❌ Polling PluralKit API - use webhooks instead
❌ Synchronous database calls - use async/await
❌ Custom webhook signature verification - use nacl library
❌ Unbounded emoji history table - set expiry policies
---
## Testing Emoji Detection
```python
# test_emoji.py
import pytest
import emoji
def test_emoji_detection():
test_emoji = "😊"
assert emoji.is_emoji(test_emoji)
demojized = emoji.demojize(test_emoji)
assert demojized == ":smiling_face_with_smiling_eyes:"
@pytest.mark.asyncio
async def test_learn_emoji():
await learn_emoji("🎭", "happy performance")
meanings = await get_emoji_meanings("🎭")
assert "happy performance" in meanings
```
---
## Monitoring in Production
**Recommended additions after MVP:**
1. **Error Tracking:** Sentry for automatic error alerts
2. **Logging:** Structured logging to file or cloud
3. **Metrics:** Track command usage, emoji diversity, member growth
4. **Health Checks:** Endpoint that Railway monitors (`GET /health`)
```python
# Simple health check
@app.route('/health')
async def health(request):
return web.Response(text='OK', status=200)
```
---
## Troubleshooting Quick Fixes
| Problem | Solution |
|---------|----------|
| Bot doesn't start | Check DISCORD_TOKEN in .env |
| Slash commands not appearing | Call `await bot.sync_commands()` |
| Database locked error (SQLite) | Only one writer at a time - use PostgreSQL for scaling |
| PluralKit webhook not received | Check public URL is reachable, signature verification |
| Slow emoji lookups | Add database indices, implement Redis cache |
| Bot unresponsive | Check for sync calls blocking event loop |
---
## Next Steps
1. **Read full research:** [STACK.md](./STACK.md)
2. **Setup development environment** using checklist above
3. **Start with MVP:** SQLite, slash commands, Vivi user detection
4. **Implement PluralKit:** Webhook dispatch, member caching
5. **Test locally:** Private Discord server for development
6. **Deploy to Railway:** Connect GitHub, set environment variables
7. **Monitor in production:** Sentry, logs, metrics
8. **Iterate:** Gather feedback, add features
---
## Resources
- [discord.py Docs](https://discordpy.readthedocs.io/)
- [PluralKit API](https://pluralkit.me/api/)
- [Railway Getting Started](https://docs.railway.app/)
- [Pydantic Validation](https://docs.pydantic.dev/)
- [emoji Library](https://carpedm20.github.io/emoji/)