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>
352 lines
8.2 KiB
Markdown
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/)
|