Overview
Jill Stingray is built on the Eris Discord library, a lightweight and performant alternative to Discord.js. The bot uses a modular architecture with separate command and event systems, PostgreSQL for persistent storage, and Supabase for file storage.Core Technologies
- Discord Library: Eris v0.17.2
- Runtime: Node.js 24
- Database: PostgreSQL (via
pgdriver) - Storage: Supabase
- Process Management: Custom crash handler
- Key Libraries:
@napi-rs/canvas,chroma-js,axios
Project Structure
Bot Initialization
The bot follows a sequential startup process defined inindex.js:91-109:
- Database Initialization - Connect to PostgreSQL and create tables
- Command Loading - Load all command modules from
/commands - Event Loading - Register all event handlers from
/events - HTTP Server - Start keep-alive server on port 7860 and 8080
- Discord Connection - Connect to Discord gateway
Eris Configuration
The bot is instantiated inindex.js:22-31 with specific intents and settings:
Bot Instance Properties
The bot object is extended with custom properties inindex.js:33-36:
bot.commands- Map of loaded slash commandsbot.prefixMap- Map of command prefixes to command namesbot.pendingActions- Temporary storage for multi-step interactionsbot.settingsCache- Cached guild settings (60s TTL)
Command System
Command Structure
All commands follow this structure:Command Loading
Commands are loaded dynamically from the/commands directory in index.js:38-61:
Command Execution Flow
Commands are executed through the interaction router inevents/interactionCreate.js:6-89:
- Permission Checking - Validate permissions using guild settings
- Rule Enforcement - Check channel restrictions and enable status
- Command Execution - Call the command’s
execute()function - Error Handling - Catch and log errors gracefully
Event System
Event Structure
Events follow this structure:Event Loading
Events are registered inindex.js:63-82:
Core Events
| Event | File | Purpose |
|---|---|---|
ready | ready.js | Sync slash commands, start status rotation |
interactionCreate | interactionCreate.js | Handle slash commands and components |
messageCreate | activityTracker.js | Track user activity metrics |
messageCreate | emojiTracker.js | Track emoji usage |
messageCreate | triggerHandler.js | Auto-respond to keywords |
messageCreate | aliasLog.js | Log username changes |
guildMemberRemove | guildMemberRemove.js | Cleanup custom roles |
error | error.js | Log Discord gateway errors |
Interaction Router
The interaction router (events/interactionCreate.js) handles all Discord interactions:
Command Interactions
Handled ininteractionCreate.js:10-89. Includes permission gating using:
- Guild-specific command rules from database
- Default rules from
utils/default.js - Admin role bypass system
- Channel restrictions
Component Interactions
Handled ininteractionCreate.js:105-136. Uses a custom routing system:
"custom:confirm_overwrite" routes to commands/custom.js::handleComponent()
Autocomplete Interactions
Handled ininteractionCreate.js:92-102. Calls command-specific autocomplete handlers.
Modal Interactions
Handled ininteractionCreate.js:139-154. Routes modal submissions to command handlers.
Settings & Caching
Guild settings are cached to reduce database queries ininteractionCreate.js:20-38:
Error Handling
The bot includes a global crash handler incrashHandler.js:1-16:
Keep-Alive Server
Two HTTP servers run for health checks:- Primary Server (Port 7860) - Returns “Jill Stingray is Online!”
- Secondary Server (Port 8080 or
process.env.PORT) - Returns “Jill Stingray is mixing drinks…”
Status Rotation
The bot cycles through status messages every 30 seconds inevents/ready.js:33-47:
Command Registration
Slash commands are synced globally and to test guilds on startup inevents/ready.js:8-68:
Next Steps
- Database Schema - Learn about data storage
- Deployment - Deploy the bot to production