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>
This commit is contained in:
351
.planning/research/QUICK_REFERENCE.md
Normal file
351
.planning/research/QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# 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/)
|
||||
Reference in New Issue
Block a user