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

8.2 KiB

Quick Reference: Tech Stack Decisions

For comprehensive rationale, see 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)

# 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)

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)

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:

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

@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

@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)

# .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

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

# 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

# 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

# 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)
# 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
  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