Files
pixelpoebel/AGENTS-BOT.md
sarah 40be1e181c
Some checks failed
Auto Build and Push Docker Image / build (push) Failing after 8s
Initial: Pixelpöbel Discord Bot
- Modular Discord Bot mit TypeScript und discord.js
- Grouped Commands (/admin, /owner subcommands)
- SQLite Datenbank mit Persistenz
- Twitch Monitoring mit Stream-ID Tracking
- Konfigurierbares Warn-System (Auto-Kick/Mute/Ban)
- Mute mit verschiedenen Zeiteinheiten (sec, min, hour, day, week, month, year, perm)
- Auto-Deploy beim Start (Option 3)
- Docker Support

Features:
- /ping, /help, /twitch (online, add, remove, list)
- /admin (kick, warn, unwarn, mute, unmute, ban, unban, config)
- /owner (deploy, stats, servers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 16:29:30 +01:00

7.9 KiB
Raw Blame History

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. SQLite Database: Persistent data storage with better-sqlite3.
  5. Twitch Monitoring: Periodic API polling with Stream ID tracking.
  6. Grouped Commands: Admin/Owner 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
│   │       ├── ping.ts
│   │       ├── help.ts
│   │       ├── twitch.ts
│   │       ├── admin.ts      # All admin subcommands
│   │       └── owner.ts      # All owner subcommands
│   ├── events/
│   │   ├── ready.ts
│   │   └── interactionCreate.ts
│   └── structures/
│       ├── ExtendedClient.ts
│       ├── Command.ts
│       ├── Database.ts
│       ├── TwitchManager.ts
│       └── Deployer.ts
├── data/                     # SQLite database (volume mounted)
├── package.json
├── tsconfig.json
├── Dockerfile
├── docker-compose.yml
└── .env.example

📝 Implementation Steps

1. Project Setup

{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "nodemon --watch 'src/**/*.ts' --exec 'node --loader ts-node/esm' src/index.ts",
    "deploy": "node --loader ts-node/esm src/deploy-commands.ts"
  }
}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true
  }
}

2. Database Structure

-- guild_settings
CREATE TABLE guild_settings (
    guild_id TEXT PRIMARY KEY,
    prefix TEXT DEFAULT '!',
    mod_log_channel TEXT,
    welcome_channel TEXT,
    warn_threshold INTEGER DEFAULT 3,
    warn_action TEXT DEFAULT 'ban',
    warn_mute_duration INTEGER DEFAULT 1800
);

-- mod_logs
CREATE TABLE mod_logs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    guild_id TEXT,
    user_id TEXT,
    moderator_id TEXT,
    action TEXT,
    reason TEXT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- command_stats
CREATE TABLE command_stats (
    command_name TEXT PRIMARY KEY,
    uses INTEGER DEFAULT 0
);

-- dm_users
CREATE TABLE dm_users (
    user_id TEXT PRIMARY KEY,
    username TEXT,
    last_seen DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- twitch_monitors
CREATE TABLE twitch_monitors (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    guild_id TEXT,
    channel_name TEXT,
    discord_channel_id TEXT,
    custom_message TEXT,
    last_status TEXT DEFAULT 'offline',
    last_stream_id TEXT,
    UNIQUE(guild_id, channel_name)
);

-- auto_responses
CREATE TABLE auto_responses (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    guild_id TEXT,
    trigger_word TEXT,
    response_text TEXT,
    UNIQUE(guild_id, trigger_word)
);

3. Key Components

ExtendedClient.ts:

import { Client, Collection, GatewayIntentBits } from 'discord.js';
import { Command } from './Command.js';

export class ExtendedClient extends Client {
    public commands: Collection<string, Command> = new Collection();

    constructor() {
        super({
            intents: [
                GatewayIntentBits.Guilds,
                GatewayIntentBits.GuildMessages,
                GatewayIntentBits.MessageContent,
                GatewayIntentBits.GuildMembers,
            ],
        });
    }
}

Command Interface:

export interface Command {
    data: any;
    category: 'Owner' | 'Admin' | 'Public';
    execute: (interaction: any, client: any) => Promise<void> | void;
    cooldown?: number;
}

Deployer - Auto-Deploy (Option 3):

export class Deployer {
    static async deployIfMissing(clientId: string, token: string) {
        const rest = new REST().setToken(token);

        try {
            const data = await rest.get(Routes.applicationCommands(clientId));
            if (data.length > 0) {
                console.log('[DEPLOYER] Commands already registered. Skipping deployment.');
                return data.length;
            }
        } catch (error) {
            // Commands don't exist yet
        }

        return this.deploy(clientId, token);
    }
}

4. Command Examples

Grouped Command (admin):

data: new SlashCommandBuilder()
    .setName('admin')
    .setDescription('Admin-Commands')
    .addSubcommand(sub => sub.setName('kick').setDescription('Kickt einen Nutzer')
        .addUserOption(opt => opt.setName('target').setDescription('Nutzer').setRequired(true))
        .addStringOption(opt => opt.setName('reason').setDescription('Grund')))
    .addSubcommand(sub => sub.setName('warn').setDescription('Verwarnt einen Nutzer')
        .addUserOption(opt => opt.setName('target').setDescription('Nutzer').setRequired(true))
        .addStringOption(opt => opt.setName('reason').setDescription('Grund').setRequired(true)))
    // ... more subcommands

5. Twitch Monitoring with Stream ID

// Stream ID tracking prevents duplicate notifications
const isNewStream = monitor.last_stream_id !== stream.id;
const wasOffline = monitor.last_status === 'offline';

if (wasOffline || (monitor.last_status === 'online' && isNewStream)) {
    // Send notification
    DB.run('UPDATE twitch_monitors SET last_status = "online", last_stream_id = ? WHERE id = ?',
        stream.id, monitor.id);
}

6. Configurable Warn System

Database Schema:

  • warn_threshold: Number of warns before action
  • warn_action: 'none', 'kick', 'mute', 'ban'
  • warn_mute_duration: Duration in seconds for mute

Auto-Action Logic:

const warnCount = countResult?.count ?? 0;
const warnThreshold = settings?.warn_threshold ?? 3;
const warnAction = settings?.warn_action ?? 'ban';

if (warnCount >= warnThreshold) {
    if (warnAction === 'kick') await target.kick(...);
    else if (warnAction === 'mute') await target.timeout(duration, ...);
    else if (warnAction === 'ban') await target.ban(...);
}

7. Mute with Multiple Time Units

const unitSeconds: Record<string, number> = {
    sec: 1,
    min: 60,
    hour: 60 * 60,
    day: 60 * 60 * 24,
    week: 60 * 60 * 24 * 7,
    month: 60 * 60 * 24 * 30,
    year: 60 * 60 * 24 * 365
};

if (unit === 'perm') {
    durationMs = null; // Permanent
} else {
    durationMs = duration * unitSeconds[unit!] * 1000;
}

🚀 Build & Deploy

# Build
npm run build

# Deploy Commands
npm run deploy

# Run
npm start

# Docker
docker-compose up -d --build

⚠️ Critical Constraints

  1. Environment Variables: Always use process.env, never hardcode.
  2. Type Safety: Use any for command data and execute parameters (compatibility).
  3. Interaction States: Check interaction.replied before replying.
  4. Twitch API: Max 100 channels per request, batch properly.
  5. Deploy: Commands NOT auto-registered on start use /owner deploy.

📋 Command Summary

Command Subcommands Permission
/ping Public
/help Public
/twitch online, add, remove, list Public/Admin
/admin kick, warn, unwarn, mute, unmute, ban, unban, config Admin
/owner deploy, stats, servers Owner