# NEXUS Bot API v2.3

NEXUS Bot Platform; REST API, resumable WebSocket Gateway, application commands, interactions, embeds/components, OAuth2, scoped API keys, signed webhooks ve moderasyon/kanal/rol/voice API'lerini tek platformda sunar.

## Base URLs

```text
REST:    https://YOUR_DOMAIN/api/v1
Gateway: wss://YOUR_DOMAIN:8081
OAuth2:  https://YOUR_DOMAIN/oauth2/authorize.php
```

## Authentication

Bot REST isteklerinde:

```http
Authorization: Bot nx_bot_...
```

Scoped API key için aynı format kullanılır:

```http
Authorization: Bot nx_key_...
```

API key yalnızca kendisine verilen route scope'larına erişebilir. Production ortamında mümkün olduğunda scoped key + IP allowlist kullanılması önerilir.

## Rate limits

Her route dakika bazlı bucket ile limitlenir. Response header'ları:

```text
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset
X-RateLimit-Reset-After
X-RateLimit-Bucket
Retry-After
```

`nexus.js` SDK 429 cevaplarında otomatik retry uygular.

## Gateway protocol

| Opcode | Name | Açıklama |
|---:|---|---|
| 0 | DISPATCH | Event payload |
| 1 | HEARTBEAT | Son sequence ile heartbeat |
| 2 | IDENTIFY | Token, intents ve shard ile oturum aç |
| 6 | RESUME | Session ID + sequence ile devam |
| 9 | INVALID_SESSION | Session yeniden başlatılmalı |
| 10 | HELLO | Heartbeat interval |
| 11 | HEARTBEAT_ACK | Heartbeat onayı |

IDENTIFY:

```json
{
  "op": 2,
  "d": {
    "token": "nx_bot_...",
    "intents": 29,
    "shard": [0, 1]
  }
}
```

## Gateway intents

```js
GatewayIntentBits.Guilds          // 1
GatewayIntentBits.GuildMembers    // 2
GatewayIntentBits.GuildMessages   // 4
GatewayIntentBits.MessageContent  // 8
GatewayIntentBits.Interactions    // 16
GatewayIntentBits.Presences       // 32
GatewayIntentBits.VoiceStates     // 64
GatewayIntentBits.GuildReactions  // 128
```

## Slash commands

`PUT /bot/commands.php` global command listesini bulk-overwrite eder. Payload'da bulunmayan eski komutlar silinir. `POST/PATCH` tekil upsert için kullanılabilir.

Desteklenen option type'ları:

- `subcommand`
- `subcommand_group`
- `string`
- `integer`
- `number`
- `boolean`
- `user`
- `channel`
- `role`
- `mentionable`
- `attachment`

Örnek:

```js
const commands = [
  new SlashCommandBuilder()
    .setName('timeout')
    .setDescription('Bir üyeye timeout uygular')
    .setDefaultMemberPermissions(PermissionFlagsBits.TimeoutMembers)
    .addUserOption(o => o
      .setName('user')
      .setDescription('Kullanıcı')
      .setRequired(true))
    .addIntegerOption(o => o
      .setName('minutes')
      .setDescription('Dakika')
      .setRequired(true)
      .setMinValue(1)
      .setMaxValue(10080))
    .addStringOption(o => o
      .setName('reason')
      .setDescription('Sebep')
      .setMaxLength(300))
];

await client.registerCommands(commands);
```

Subcommand:

```js
new SlashCommandBuilder()
  .setName('role')
  .setDescription('Rol yönetimi')
  .addSubcommand(s => s
    .setName('add')
    .setDescription('Rol ver')
    .addUserOption(o => o.setName('user').setDescription('Kullanıcı').setRequired(true))
    .addRoleOption(o => o.setName('role').setDescription('Rol').setRequired(true)))
  .addSubcommand(s => s
    .setName('remove')
    .setDescription('Rol kaldır')
    .addUserOption(o => o.setName('user').setDescription('Kullanıcı').setRequired(true))
    .addRoleOption(o => o.setName('role').setDescription('Rol').setRequired(true)));
```

## Interactions

Slash command eventleri `INTERACTION_CREATE` olarak gelir. `nexus.js` içinde `Interaction` ve `InteractionOptionResolver` kullanılır.

```js
client.on('interactionCreate', async interaction => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === 'timeout') {
    const user = interaction.options.getUser('user', true);
    const minutes = interaction.options.getInteger('minutes', true);
    const reason = interaction.options.getString('reason') || 'Sebep belirtilmedi';

    await client.timeout(interaction.guildId, user.id, minutes, reason);
    await interaction.reply({ content: 'Timeout uygulandı.', ephemeral: true });
  }
});
```

Resolver metodları:

```text
get(name)
getString(name)
getInteger(name)
getNumber(name)
getBoolean(name)
getUser(name)
getChannel(name)
getRole(name)
getMentionable(name)
getAttachment(name)
getSubcommand()
getSubcommandGroup()
```

Interaction helpers:

```text
reply(payload)
deferReply({ ephemeral })
update(payload)
showModal(modal)
followUp(payload)
```

## Embeds

```js
const embed = new EmbedBuilder()
  .setTitle('Sunucu Bilgisi')
  .setDescription('NEXUS bot embed')
  .setColor('#5865f2')
  .addFields(
    { name: 'Üye', value: '120', inline: true },
    { name: 'Kanal', value: '18', inline: true }
  );

await client.send(CHANNEL_ID, { embeds: [embed] });
```

Limitler: mesaj başına en fazla 10 embed, embed başına en fazla 25 field.

## Components

```js
const row = new ActionRowBuilder().addComponents(
  new ButtonBuilder()
    .setCustomId('ticket:create')
    .setLabel('Ticket Aç')
    .setStyle(ButtonStyle.Primary),

  new ButtonBuilder()
    .setURL('https://example.com')
    .setLabel('Web Site')
);

await client.send(CHANNEL_ID, {
  content: 'Destek menüsü',
  components: [row]
});
```

## Modals

```js
await interaction.showModal(
  new ModalBuilder()
    .setCustomId('report')
    .setTitle('Rapor')
    .addFields(
      new TextInputBuilder()
        .setCustomId('reason')
        .setLabel('Sebep')
        .setStyle(TextInputStyle.Paragraph)
        .setMaxLength(1000)
    )
);
```

## Messages

```js
await client.send(CHANNEL_ID, 'Merhaba');
await client.editMessage(MESSAGE_ID, { content: 'Düzenlendi' });
await client.deleteMessage(MESSAGE_ID);
await client.react(MESSAGE_ID, '✅');
await client.unreact(MESSAGE_ID, '✅');
```

Dosya:

```js
await client.sendFiles(CHANNEL_ID, ['./report.pdf', './image.png'], {
  content: 'Dosyalar hazır.'
});
```

## Guilds, members, channels and roles

```js
const guilds = await client.fetchGuilds();
const members = await client.fetchMembers(GUILD_ID, { limit: 100 });
const channels = await client.fetchChannels(GUILD_ID);
const roles = await client.fetchRoles(GUILD_ID);

const channel = await client.createChannel(GUILD_ID, {
  name: 'bot-log', type: 'text', topic: 'Bot kayıtları'
});

const role = await client.createRole(GUILD_ID, {
  name: 'Destek', color: '#5865f2', permissions: 3
});

await client.addRole(GUILD_ID, USER_ID, role.role_id);
await client.removeRole(GUILD_ID, USER_ID, role.role_id);
```

## Moderation

```js
await client.kick(GUILD_ID, USER_ID, 'Kural ihlali');
await client.ban(GUILD_ID, USER_ID, 'Spam');
await client.unban(GUILD_ID, USER_ID, 'İtiraz kabul edildi');
await client.timeout(GUILD_ID, USER_ID, 10, 'Flood');
await client.removeTimeout(GUILD_ID, USER_ID);
await client.setNickname(GUILD_ID, USER_ID, 'Yeni isim');
```

Kurulum permission maskesi, botun runtime kanal/sunucu permission'ları ve rol hiyerarşisi birlikte doğrulanır.

## Command permissions

```js
const rules = await client.fetchCommandPermissions(GUILD_ID, COMMAND_ID);

await client.setCommandPermissions(GUILD_ID, COMMAND_ID, [
  { role_id: MODERATOR_ROLE_ID, allow: true },
  { channel_id: OFF_TOPIC_CHANNEL_ID, allow: false }
]);
```

## Voice state

```js
await client.joinVoice(VOICE_CHANNEL_ID, { speaking: true });
await client.setVoiceState({ is_muted: false, speaking: true });
await client.leaveVoice();
```

## Presence

```js
await client.setPresence({
  status: 'online',
  activity_text: '/help'
});
```

## Webhooks

Webhook eventleri HMAC-SHA256 ile imzalanır:

```text
signature = HMAC_SHA256(webhookSecret, timestamp + "." + rawRequestBody)
```

Headers:

```text
X-Nexus-Timestamp
X-Nexus-Signature: sha256=...
X-Nexus-Event
```

Timestamp freshness kontrolü ve constant-time signature karşılaştırması önerilir.

## Secret Vault

```js
const all = await client.fetchSecrets();
const one = await client.fetchSecrets('OPENAI_KEY');
```

Secret değerlerini hiçbir zaman loglama.

## Gateway events

```text
ready
resumed
messageCreate
messageUpdate
messageDelete
messageReactionAdd
messageReactionRemove
guildMemberAdd
guildMemberUpdate
guildMemberRemove
guildBanAdd
guildBanRemove
channelCreate
channelUpdate
channelDelete
roleCreate
roleUpdate
roleDelete
voiceStateUpdate
guildCreate
guildDelete
interactionCreate
presenceUpdate
raw
debug
error
```

## Error handling

```js
import { NexusAPIError } from 'nexus.js';

try {
  await client.ban(GUILD_ID, USER_ID);
} catch (error) {
  if (error instanceof NexusAPIError) {
    console.error(error.status, error.message, error.rateLimit);
  }
}
```

Standard response:

```json
{
  "success": false,
  "message": "Bu işlem için bot izni yok.",
  "data": null
}
```

HTTP statusları: `400`, `401`, `403`, `404`, `429`, `500`.

## Security checklist

1. Token ve secret değerlerini frontend'e gönderme.
2. `.env` dosyasını version control dışında tut.
3. Scoped API key ile minimum yetki kullan.
4. Production için IP allowlist tanımla.
5. Webhook signature doğrula.
6. Credential sızıntısında reset/revoke et.
7. Message Content intentini yalnızca gerekiyorsa aç.
8. Bot permissionlarını Administrator yerine ihtiyaç kadar ver.

## OpenAPI

Makine tarafından okunabilir API tanımı: `openapi.json`.
