Files
pixelpoebel/AGENTS-BOT.md

5.9 KiB

AI Agent Guide: Pixelpöbel Discord Bot

This document is intended for AI agents to understand and recreate the pixelpöbel Discord bot.

🏗 Architecture Overview

The bot uses a Modular Command & Event Loading pattern with ESM (ECMAScript Modules) and TypeScript.

Key Design Patterns:

  1. Extended Client Pattern: Extend discord.js Client class to hold global state.
  2. Dynamic Discovery: index.ts uses readdirSync and dynamic import() to register commands/events.
  3. Interface-Driven Commands: All commands implement Command interface.
  4. Optimized SQLite Database: Persistent storage with better-sqlite3, utilizing WAL (Write-Ahead Logging) and In-Memory Caching for frequently accessed data.
  5. Twitch Monitoring: Periodic API polling using Batch-Requests (100 channels per request) with Stream ID tracking.
  6. TwitchMonitor IRC: TMI.js-based IRC chat monitoring for mod events.
  7. Reminder System: Periodic reminder checking with target_time tracking.
  8. Auto-Response System: Trigger word detection for automatic replies (cached).
  9. Welcome/Goodbye System: Guild member add/remove events with customizable messages.
  10. Logging System: Configurable event logging (messages, roles, moderation, etc.).
  11. Role Selection System: Self-service role assignment via select menus.
  12. Grouped Commands: Admin/Owner/Trigger/Timer commands grouped under subcommands.

📁 Project Structure

pixelpoebel/
├── src/
│   ├── index.ts              # Entry point, loads commands/events
│   ├── deploy-commands.ts    # Deploy script for Discord
│   ├── commands/
│   │   └── utility/          # All commands grouped here
│   ├── events/
│   │   ├── ...               # All Discord event handlers
│   └── structures/
│       ├── ExtendedClient.ts
│       ├── Command.ts
│       ├── Database.ts       # Database with Caching logic
│       ├── TwitchManager.ts  # Batch Polling logic
│       ├── TwitchMonitor.ts  # IRC Monitoring logic
│       ├── TwitchCache.ts    # IRC Message FIFO Cache
│       ├── ReminderManager.ts
│       └── Deployer.ts
├── data/                     # SQLite database (volume mounted)
├── package.json
├── tsconfig.json
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── .gitattributes

📝 Implementation Steps

1. Database with Caching

The database uses WAL mode for performance and an in-memory Map for caching settings and triggers.

// src/structures/Database.ts
export class DB {
    private static settingsCache = new Map<string, any>();
    private static triggersCache = new Map<string, any[]>();

    static init() {
        db.pragma('journal_mode = WAL');
        // ... Table creation ...
    }

    static getSettings(guildId: string) {
        if (this.settingsCache.has(guildId)) return this.settingsCache.get(guildId);
        const settings = db.prepare('SELECT * FROM guild_settings WHERE guild_id = ?').get(guildId);
        if (settings) this.settingsCache.set(guildId, settings);
        return settings;
    }

    static run(query: string, ...params: any[]) {
        const result = db.prepare(query).run(...params);
        if (query.toLowerCase().includes('guild_settings') || query.toLowerCase().includes('auto_responses')) {
            this.settingsCache.clear();
            this.triggersCache.clear();
        }
        return result;
    }
}

2. Twitch Batch Polling

To stay within API limits and provide faster updates, the bot polls Twitch in batches of 100.

// src/structures/TwitchManager.ts
static async checkStreams(client: any) {
    const monitors = client.DB.all('SELECT * FROM twitch_monitors');
    const uniqueChannels = [...new Set(monitors.map(m => m.channel_name.toLowerCase()))];

    for (let i = 0; i < uniqueChannels.length; i += 100) {
        const chunk = uniqueChannels.slice(i, i + 100);
        const query = chunk.map(name => `user_login=${encodeURIComponent(name)}`).join('&');
        // fetch https://api.twitch.tv/helix/streams?${query}
        // ... process results ...
    }
}

static startPolling(client: any) {
    setInterval(() => this.checkStreams(client), 2 * 60 * 1000); // 2 minute interval
}

3. Event Logging Optimization

All logging events use a centralized sendLog pattern that utilizes the DB.getSettings() cache.

async function sendLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
    const settings = client.DB.getSettings(guildId);
    if (!settings?.log_events || !settings?.log_channel) return;
    
    const activeEvents = settings.log_events.split(',').filter(Boolean);
    if (!activeEvents.includes(event)) return;

    const channel = client.guilds.cache.get(guildId)?.channels.cache.get(settings.log_channel);
    if (channel?.isTextBased()) await channel.send({ embeds: [embed] });
}

4. TwitchMonitor IRC Chat Logging

Overview: Uses TMI.js to connect to Twitch IRC and logs moderation events (bans, timeouts, deletes) via webhooks.

Key Feature: FIFO Message Cache (TwitchCache.ts) allows restoring the text of deleted messages in the logs.

🚀 Performance Benchmarks (approx.)

Metric Old (Individual) New (Batch/Cached)
API Calls (500 channels) 500 5
DB Access (Triggers) Disk I/O per msg RAM access
Notification Delay ~5-7 min ~2 min

⚠️ Critical Constraints

  1. Batching: Never exceed 100 channels per Twitch API request.
  2. Caching: Always invalidate cache (clearCache) when updating settings.
  3. WAL Mode: Ensure the data/ directory has proper permissions for .shm and .wal files.
  4. Webhook Safety: Use WebhookClient for Twitch IRC logging to avoid Discord bot rate limits.