# API Integration

### ✨ Features

* **Event-driven architecture** — React to Discord and bot events
* **Backward compatibility** — Legacy addons still work
* **Priority system** — Control execution order of handlers
* **Error isolation** — One addon's error won't crash others
* **Rich context** — Access client, config, and language data
* **Async support** — Full `Promise` / `async-await` support

***

### 🚀 Quick Start

#### Example: HelloWorld Addon

A simple addon that responds to messages, welcomes new members, and reacts to tickets being created:

{% code expandable="true" %}

```javascript
module.exports = {
    // Only 'name' is required!
    name: 'HelloWorld',
    
    // Everything else is optional (but recommended for clarity)
    // version: '1.0.0'
    // description: '...'
    // author: 'Your Name'
    
    events: {
        // Respond to messages
        'discord:messageCreate': async (eventData, context) => {
            const { message } = eventData;
            if (message.author.bot) return;
            
            if (message.content.toLowerCase() === '!hello') {
                await message.channel.send(`Hello ${message.author.username}! 👋`);
            }
        },
        
        // Welcome new members
        'discord:guildMemberAdd': async (eventData, context) => {
            const { member } = eventData;
            console.log(`New member joined: ${member.user.username}`);
            
            const channel = member.guild.channels.cache.find(
                ch => ch.name === 'welcome' || ch.name === 'general'
            );
            if (channel) {
                await channel.send(`Welcome ${member.user.username}! 🎉`);
            }
        },
        
        // React to tickets being created
        'ticket:created': async (eventData, context) => {
            const { ticket, user } = eventData;
            console.log(`Ticket #${ticket.ticketId} was created by ${user.username}`);
        }
    }
};
```

{% endcode %}

#### ✅ With this addon

* Type `!hello` → Bot replies with a greeting
* New members join → Welcome message in **#welcome** or **#general**
* Ticket is created → Logged in console

***

### 📡 Event Reference

#### Discord Events

Listen to Discord.js events with the `discord:` prefix:

| Event                       | What It Does                | Key Data                 |
| --------------------------- | --------------------------- | ------------------------ |
| `discord:messageCreate`     | New message sent            | `message`                |
| `discord:messageUpdate`     | Message edited              | `message`, `oldMessage`  |
| `discord:messageDelete`     | Message deleted             | `message`                |
| `discord:guildMemberAdd`    | User joins server           | `member`                 |
| `discord:guildMemberRemove` | User leaves server          | `member`                 |
| `discord:guildMemberUpdate` | User roles/nickname changed | `oldMember`, `newMember` |
| `discord:voiceStateUpdate`  | Voice channel changes       | `oldState`, `newState`   |
| `discord:channelCreate`     | Channel created             | `channel`                |
| `discord:channelDelete`     | Channel deleted             | `channel`                |
| `discord:roleCreate`        | Role created                | `role`                   |
| `discord:roleDelete`        | Role deleted                | `role`                   |
| `discord:guildBanAdd`       | User banned                 | `ban`                    |
| `discord:guildBanRemove`    | User unbanned               | `ban`                    |
| `discord:interactionCreate` | Slash command/button used   | `interaction`            |
| `discord:ready`             | Bot started                 | `client`                 |

#### Bot Business Logic Events

**Ticket Events**

| Event              | What It Does                 | Key Data                                           |
| ------------------ | ---------------------------- | -------------------------------------------------- |
| `ticket:created`   | New ticket opened            | `ticket`, `user`, `ticketType`, `questions`        |
| `ticket:closed`    | Ticket closed/resolved       | `ticket`, `closedBy`, `closeReason`, `isAutoAlert` |
| `ticket:deleted`   | Ticket channel deleted       | `ticket`, `deletedBy`, `channelName`               |
| `ticket:claimed`   | Staff member claims ticket   | `ticket`, `claimer`                                |
| `ticket:unclaimed` | Staff member unclaims ticket | `ticket`, `previousClaimer`                        |
| `ticket:reviewed`  | User reviews service         | `ticket`, `rating`, `feedback`, `reviewer`         |

**Suggestion Events**

| Event                 | What It Does                 | Key Data                                               |
| --------------------- | ---------------------------- | ------------------------------------------------------ |
| `suggestion:created`  | New suggestion submitted     | `suggestion`, `author`, `text`, `message`              |
| `suggestion:accepted` | Suggestion approved by staff | `suggestion`, `acceptedBy`, `reason`, `originalAuthor` |
| `suggestion:denied`   | Suggestion rejected by staff | `suggestion`, `deniedBy`, `reason`, `originalAuthor`   |

**Leveling Events**

| Event      | What It Does                | Key Data                                               |
| ---------- | --------------------------- | ------------------------------------------------------ |
| `level:up` | User gains XP and levels up | `user`, `newLevel`, `oldLevel`, `xpGained`, `userData` |

**Auto-Moderation Events**

| Event                    | What It Does                     | Key Data                                                |
| ------------------------ | -------------------------------- | ------------------------------------------------------- |
| `autoReact:triggered`    | Bot auto-reacts to keyword       | `message`, `keyword`, `emoji`, `reaction`               |
| `autoResponse:triggered` | Bot sends auto-response          | `message`, `trigger`, `responseType`, `responseContent` |
| `moderation:antiSpam`    | Anti-spam/mass mention triggered | `type`, `user`, `action`, `reason`, `duration`          |

**Music Events**

| Event              | What It Does         | Key Data                        |
| ------------------ | -------------------- | ------------------------------- |
| `music:trackStart` | Track starts playing | `track`, `requestedBy`, `queue` |
| `music:trackAdded` | Track added to queue | `track`, `requestedBy`, `queue` |

**Giveaway Events**

| Event              | What It Does                        | Key Data                                       |
| ------------------ | ----------------------------------- | ---------------------------------------------- |
| `giveaway:created` | New giveaway started                | `giveaway`, `prize`, `winnerCount`, `hostedBy` |
| `giveaway:ended`   | Giveaway finished, winners selected | `giveaway`, `winners`, `prize`, `totalEntries` |

**Invite Events**

| Event                 | What It Does                    | Key Data                                  |
| --------------------- | ------------------------------- | ----------------------------------------- |
| `invite:memberJoined` | Member joins via tracked invite | `member`, `inviter`, `inviterInviteCount` |

**Moderation Events (Slash Commands)**

| `moderation:ban`             | A user is banned via slash command or audit log | `type`, `target`, `moderator`, `reason`, `guild`, `dmSent`, `method`                                       |
| ---------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `moderation:unban`           | A previously banned user is unbanned            | `type`, `targetUserId`, `moderator`, `reason`, `guild`, `method`                                           |
| `moderation:kick`            | A member is removed from the server             | `type`, `target`, `moderator`, `reason`, `guild`, `dmSent`, `method`                                       |
| `moderation:warn`            | A moderator issues a warning                    | `type`, `target`, `moderator`, `reason`, `guild`, `warningCount`, `warning`, `method`                      |
| `moderation:unwarn`          | A warning is removed from a user                | `type`, `target`, `moderator`, `removedWarning`, `warningId`, `guild`, `remainingWarnings`, `method`       |
| `moderation:timeout`         | A user is muted/timed out                       | `type`, `subType`, `target`, `moderator`, `reason`, `duration`, `durationMs`, `endTime`, `guild`, `method` |
| `moderation:timeout_clear`   | Timeout or mute is lifted                       | `type`, `target`, `moderator`, `guild`, `wasMuted`, `method`                                               |
| `moderation:tempban`         | A moderator applies a timed ban                 | `type`, `target`, `moderator`, `reason`, `duration`, `endTime`, `guild`, `dmSent`, `method`                |
| `moderation:nickname_change` | A moderator edits a user’s nickname             | `type`, `target`, `moderator`, `oldNickname`, `newNickname`, `guild`, `method`                             |
| `moderation:purge`           | A moderator bulk deletes messages               | `type`, `moderator`, `channel`, `guild`, `messageCount`, `purgeType`, `originalAmount`, `method`           |

**Addon Lifecycle Events**

| Event              | What It Does                       | Key Data               |
| ------------------ | ---------------------------------- | ---------------------- |
| `addon:loaded`     | Addon loaded successfully          | `name`, `path`, `type` |
| `addon:unloaded`   | Addon unloaded                     | `name`, `path`         |
| `addon:registered` | Addon registered with event system | `name`, `events`       |

***

### 🔧 Custom Events

Emit and listen for your own events:

{% code expandable="true" %}

```javascript
// Emit
global.addonLoader.getEventManager().emitSafe('my-addon:custom-event', {
    data: 'some data',
    user,
    guild
});

// Listen
events: {
    'my-addon:custom-event': async (eventData, context) => {
        const { data, user, guild } = eventData;
        // Handle custom event
    }
}
```

{% endcode %}

***

### 🧰 Context Object

Every handler receives:

{% code expandable="true" %}

```javascript
{
    client: Client,       // Discord.js client
    config: Object,       // Bot config
    lang: Object,         // Language config
    eventName: String,    // Current event
    timestamp: Date,      // Emitted at
    guild: Guild|null,    // Guild if available
    user: User|null       // User if available
}
```

{% endcode %}

***

### ⚙️ Advanced Features

#### Priority System

Control execution order:

```javascript
module.exports = {
    name: 'HighPriority',
    priority: 100, // Higher runs first
    events: { /* ... */ }
};
```

#### Error Handling

Addons run independently:

{% code expandable="true" %}

```javascript
events: {
    'discord:messageCreate': async (eventData, context) => {
        try {
            // your logic
        } catch (err) {
            console.error('Error in my addon:', err);
            // Won't crash other addons
        }
    }
}
```

{% endcode %}

#### Database Integration

Use Mongoose inside addons:

{% code expandable="true" %}

```javascript
const mongoose = require('mongoose');

const mySchema = new mongoose.Schema({
    guildId: String,
    data: String
});

const MyModel = mongoose.model('MyData', mySchema);

// Use in events
await MyModel.findOneAndUpdate(
    { guildId: guild.id },
    { data: 'updated' },
    { upsert: true }
);
```

{% endcode %}

#### Conditional Event Handling

Run logic only in certain channels/users:

{% code expandable="true" %}

```javascript
'discord:messageCreate': async (eventData, context) => {
    const { message } = eventData;
    
    // Only in specific channels
    if (!['general', 'bot-commands'].includes(message.channel.name)) return;
    
    // Only non-bots
    if (message.author.bot) return;
    
    // Your logic here
}
```

{% endcode %}

***

### 🔄 Migration from Legacy Addons

#### Legacy Format (still works)

{% code expandable="true" %}

```javascript
module.exports = {
    run: async (client) => {
        client.on('messageCreate', async message => {
            if (message.content === '!hello') {
                await message.channel.send('Hello!');
            }
        });
    }
};
```

{% endcode %}

#### New Event API Format

{% code expandable="true" %}

```javascript
module.exports = {
    name: 'MyAddon',
    version: '1.0.0',
    events: {
        'discord:messageCreate': async (eventData, context) => {
            const { message } = eventData;
            if (message.content === '!hello') {
                await message.channel.send('Hello!');
            }
        }
    },
    
    // Optional: Keep initialization logic
    run: async (client, eventManager) => {
        console.log('Addon initialized!');
    }
};
```

{% endcode %}

#### Key Differences

* **Legacy** → `run` function, no `name` property
* **New** → `name` required, uses `events`
* **New format benefits:** event-driven API, hot reloading, enable/disable, error isolation, priorities

***

### 📋 Requirements Summary

#### Absolutely Required

* `name` (string) — Unique addon identifier

#### Required (pick one)

* `events` (object) — Event handlers
* `run` (function) — Init function

#### Optional (defaults)

* `version` → `'1.0.0'`
* `description` → `''`
* `author` → `'Unknown'`
* `priority` → `0`
* `permissions` → `[]`
* `dependencies` → `[]`

#### Minimal Working Addon

```javascript
module.exports = {
    name: 'Minimal',
    events: {
        'discord:messageCreate': async (eventData, context) => {
            // Your code here
        }
    }
};
```

***

### 💡 Practical Examples

#### Staff Notification System

{% code expandable="true" %}

```javascript
module.exports = {
    name: 'StaffNotifications',
    events: {
        'ticket:created': async ({ ticket, user, ticketType }) => {
            const staffChannel = ticket.guild.channels.cache.find(ch => ch.name === 'staff-alerts');
            if (staffChannel) {
                await staffChannel.send(`🎫 New ${ticketType.Name} ticket #${ticket.ticketId} by ${user.username}`);
            }
        },
        
        'suggestion:created': async ({ suggestion, author, text }) => {
            const staffChannel = suggestion.guild.channels.cache.find(ch => ch.name === 'suggestions');
            if (staffChannel) {
                const message = await staffChannel.send(`💡 New suggestion: "${text}" by ${author.username}`);
                await message.react('👍');
                await message.react('👎');
            }
        }
    }
};
```

{% endcode %}

#### Level Rewards System

{% code expandable="true" %}

```javascript
module.exports = {
    name: 'LevelRewards',
    events: {
        'level:up': async ({ user, newLevel, guild }) => {
            const member = guild.members.cache.get(user.id);
            
            // Milestone rewards
            if (newLevel === 10) {
                const role = guild.roles.cache.find(r => r.name === 'Active Member');
                if (role) await member.roles.add(role);
            }
            
            if (newLevel === 50) {
                const role = guild.roles.cache.find(r => r.name === 'Veteran');
                if (role) await member.roles.add(role);
            }
            
            // Celebrate big milestones
            if (newLevel % 25 === 0) {
                const channel = guild.channels.cache.find(ch => ch.name === 'general');
                if (channel) {
                    await channel.send(`🎉 ${user.username} reached level ${newLevel}! Amazing! 🎉`);
                }
            }
        }
    }
};
```

{% endcode %}

#### Auto-Moderation Logger

{% code expandable="true" %}

```javascript
module.exports = {
    name: 'ModLogger',
    events: {
        'moderation:antiSpam': async ({ type, user, action, reason, guild }) => {
            const logChannel = guild.channels.cache.find(ch => ch.name === 'mod-logs');
            if (logChannel) {
                await logChannel.send({
                    embeds: [{
                        title: '🛡️ Auto-Moderation',
                        description: `**User:** ${user.username}\n**Type:** ${type}\n**Action:** ${action}\n**Reason:** ${reason}`,
                        color: 0xff6b6b,
                        timestamp: new Date()
                    }]
                });
            }
        }
    }
};
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.drakodevelopment.net/addon-system/api-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
