简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

Документация по функциям платформы Discord

DiscordAdapter — это адаптер, построенный на протоколах Discord Gateway (WebSocket) и REST API v10, объединяющий основные функции Discord Bot и предоставляющий единый интерфейс для обработки событий и операций с сообщениями.


Информация о документации

Основная информация

Описание конфигурации

DiscordAdapter поддерживает конфигурацию нескольких аккаунтов, каждый аккаунт соответствует отдельному Discord-боту.

# config.toml

# Аккаунт 1
[DiscordAdapter.accounts.default]
token = "YOUR_BOT_TOKEN"       # Discord Bot Token (обязательно)
intents = 33281                 # Gateway Intents (необязательно, по умолчанию 33281)
enabled = true                  # Включить (необязательно, по умолчанию true)

# Аккаунт 2
[DiscordAdapter.accounts.bot2]
token = "ANOTHER_BOT_TOKEN"
intents = 33281
enabled = true

Описание параметров конфигурации (для каждого аккаунта):

Gateway Intents

Intents используют bitmask, вычисляются путем побитового OR (|) значений каждого Intent:

Intent Bit Значение Описание Привилегированный
GUILDS 1 << 0 1 Создание/удаление/обновление серверов, каналов, изменение ролей Нет
GUILD_MEMBERS 1 << 1 2 Участие/выход/обновление участников Да
GUILD_MESSAGES 1 << 9 512 Отправка/получение сообщений на сервере Нет
MESSAGE_CONTENT 1 << 15 32768 Содержимое сообщений (без этого Intent значение content будет пустым) Да

Значение по умолчанию 33281 = GUILDS(1) | GUILD_MESSAGES(512) | MESSAGE_CONTENT(32768).

Внимание: Привилегированные Intents необходимо включить в Discord Developer Portal → Bot → Privileged Gateway Intents. Если бот находится на более чем 100 серверах, также требуется прохождение проверки Discord.

API-среда:

Обновление до v5 (4.2.0)

Данный адаптер был обновлен до соответствия v5 (постепенное обновление, совместимость API сохранена):

Стандартные API-действия

from ErisPulse import sdk
discord = sdk.adapter.get("discord")

result = await discord.Api.get_self_info()                # GET /users/@me
result = await discord.Api.get_user_info(user_id)         # GET /users/{id}
result = await discord.Api.get_guild_info(guild_id)       # GET /guilds/{id}
result = await discord.Api.get_guild_list()               # GET /users/@me/guilds
result = await discord.Api.get_channel_list(guild_id)     # GET /guilds/{id}/channels
result = await discord.Api.get_guild_member_info(gid, uid)
await discord.Api.delete_message(message_id)              # Автоматически дополняется channel_id
await discord.Api.leave_guild(guild_id)
result = await discord.Api.Using("main").get_self_info()

Кнопки (keyboard / components)

rows = [[{"label": "Нажми", "type": "callback", "data": "btn:1"},
         {"label": "Сайт",  "type": "link",     "data": "https://example.com"}]]
await discord.Send.To("channel", channel_id).Keyboard(rows).Text("Выберите")
# Автоматически преобразуется в components: callback → custom_id / link → url

Поддерживаемые типы отправки сообщений

Все методы отправки сообщений реализованы с использованием цепочечного синтаксиса, например:

from ErisPulse.Core import adapter
discord = adapter.get("discord")

await discord.Send.To("group", channel_id).Text("Hello World!")

Поддерживаемые типы отправки сообщений включают:

Цепочечные модификаторы (можно комбинировать)

Цепочечные модификаторы возвращают self, позволяя цепочечное использование, обязательно должны вызываться перед окончательным методом отправки:

Примеры цепочечного вызова

# Базовая отправка
await discord.Send.To("group", channel_id).Text("Hello")

# Ответ на сообщение
await discord.Send.To("group", channel_id).Reply(msg_id).Text("Ответ на сообщение")

# Удобный ответ (одно действие)
await discord.Send.To("group", channel_id).Reply("Содержимое ответа", msg_id)

# Упоминание пользователя
await discord.Send.To("group", channel_id).At("user_id").Text("Привет")

# Упоминание нескольких пользователей
await discord.Send.To("group", channel_id).At("user1").At("user2").Text("Упоминание нескольких пользователей")

# Упоминание всех
await discord.Send.To("group", channel_id).AtAll().Text("Анонс")

# Комбинированное использование
await discord.Send.To("group", channel_id).Reply(msg_id).At("user_id").Text("Сложное сообщение")

# Встроенное сообщение
embed = {
    "title": "Уведомление",
    "description": "Это встроенное сообщение",
    "color": 5814783,
    "fields": [{"name": "Поле", "value": "Значение", "inline": True}],
}
await discord.Send.To("group", channel_id).Embed(embed)

# Отправка изображения
await discord.Send.To("group", channel_id).Image("https://example.com/image.png")

Личные сообщения

При отправке личных сообщений адаптер автоматически создает DM-канал:

# Отправка личного сообщения
await discord.Send.To("user", user_id).Text("Содержимое личного сообщения")
await discord.Send.To("user", user_id).Embed(embed)

Операции с сообщениями

# Отмена отправки сообщения
await discord.Send.To("group", channel_id).Recall(msg_id)

# OneBot12 формат
ob12_msg = [
    {"type": "text", "data": {"text": "Hello "}},
    {"type": "mention", "data": {"user_id": "user_id"}},
]
await discord.Send.To("group", channel_id).Raw_ob12(ob12_msg)

Возвращаемые значения методов отправки

Все методы отправки возвращают объект Task, который можно await-ом получить результат отправки. Возвращаемый результат соответствует стандартизированному формату возврата адаптера ErisPulse:

{
    "status": "ok",           // Статус выполнения: "ok" или "failed"
    "retcode": 0,             // Код возврата (0 — успех)
    "data": {...},            // Оригинальный ответ Discord API
    "message_id": "xxx",      // ID сообщения (при отправке сообщения)
    "message": "",            // Сообщение об ошибке
    "discord_raw": {...}      // Оригинальные данные ответа
}

Описание кодов ошибок

retcode Описание
0 Успешно
33001 Ошибка сети (ошибка подключения, таймаут и т.д.)
34000 Ошибка Discord API (недостаточно прав, неверные параметры и т.д.)

Уникальные типы событий

Необходимо использовать platform == "discord" для проверки и использования особенностей данной платформы.

Основные различия

  1. Система серверов/каналов: Discord использует двухуровневую структуру серверов (Guild) и каналов (Channel), канал является основной целью отправки сообщений
  2. События Gateway: Все события получают через WebSocket Gateway, используя механизм Opcode + Dispatch
  3. Подписка на Intents: Подписка на типы событий через bitmask, MESSAGE_CONTENT требует привилегированных прав
  4. Типы сообщений: Поддерживаются текст, изображение, файл, видео, аудио, Embed, Sticker и другие типы сообщений
  5. Формат упоминания: Discord использует формат <@user_id> для упоминания пользователей

Расширенные поля

Все дополнительные поля имеют префикс discord_:

Отображение detail_type

Сцена Discord detail_type Описание
Сообщение в канале channel Расширенный тип ErisPulse
Личное сообщение (DM) private Стандартный тип OneBot12

Отображение типов событий

Событие Discord OneBot12 type detail_type Описание
MESSAGE_CREATE message channel/private Создание сообщения
MESSAGE_UPDATE message channel/private Редактирование сообщения
MESSAGE_DELETE notice group_message_delete / private_message_delete Удаление сообщения
GUILD_MEMBER_ADD notice group_member_increase Участник присоединился
GUILD_MEMBER_REMOVE notice group_member_decrease Участник покинул
GUILD_MEMBER_UPDATE notice group_member_update Обновление информации о участнике
GUILD_ROLE_CREATE notice group_role_create Создание роли
GUILD_ROLE_DELETE notice group_role_delete Удаление роли
CHANNEL_CREATE notice channel_create Создание канала
CHANNEL_DELETE notice channel_delete Удаление канала
INTERACTION_CREATE request interaction Взаимодействие (кнопки, команды и т.д.)

Примеры специальных полей

# Текстовое сообщение в канале
{
  "type": "message",
  "detail_type": "channel",
  "user_id": "ID отправителя",
  "user_nickname": "Имя пользователя",
  "group_id": "ID канала",
  "message_id": "ID сообщения",
  "discord_raw": {...},
  "discord_raw_type": "MESSAGE_CREATE",
  "discord_guild_id": "ID сервера",
  "discord_channel_id": "ID канала",
  "message": [
    {"type": "text", "data": {"text": "Hello"}}
  ],
  "alt_message": "Hello"
}

# Личное сообщение
{
  "type": "message",
  "detail_type": "private",
  "user_id": "ID отправителя",
  "user_nickname": "Имя пользователя",
  "message_id": "ID сообщения",
  "discord_raw": {...},
  "discord_raw_type": "MESSAGE_CREATE",
  "discord_channel_id": "ID DM-канала",
  "message": [
    {"type": "text", "data": {"text": "Содержимое личного сообщения"}}
  ],
  "alt_message": "Содержимое личного сообщения"
}

# Сообщение с Embed
{
  "type": "message",
  "detail_type": "channel",
  "message": [
    {"type": "discord_embed", "data": {"embed": {...}}}
  ],
  "alt_message": "[Встроенное сообщение]"
}

# Сообщение с вложениями
{
  "type": "message",
  "detail_type": "channel",
  "message": [
    {"type": "text", "data": {"text": "Посмотри на это изображение"}},
    {"type": "image", "data": {"file": "URL изображения", "url": "URL изображения", "file_name": "image.png"}}
  ],
  "alt_message": "Посмотри на это изображение[изображение]"
}

Типы сообщений

Содержимое Discord-сообщений автоматически преобразуется в соответствующие типы сообщений на основе content, attachments, embeds:

Источник Тип преобразования Описание
Текст content text Текстовое содержимое
Текст content <@id> mention Упоминание пользователя
Текст content <@&id> discord_role_mention Упоминание роли
Текст content <#id> discord_channel_mention Упоминание канала
attachments (image/*) image Вложение изображения
attachments (video/*) video Вложение видео
attachments (audio/*) audio Вложение аудио
attachments (другое) file Вложение файла
embeds discord_embed Встроенное сообщение
sticker_items discord_sticker Наклейка

Сообщение типа discord_embed

{
  "type": "discord_embed",
  "data": {
    "embed": {
      "title": "Заголовок",
      "description": "Описание",
      "color": 12345,
      "fields": [...],
      "image": {"url": "..."},
      "thumbnail": {"url": "..."},
      "footer": {"text": "..."}
    }
  }
}

Подключение к Gateway

Процесс подключения

  1. Вызов GET /gateway/bot для получения URL WebSocket Gateway
  2. Подключение к wss://gateway.discord.gg/?v=10&encoding=json
  3. Получение opcode 10 HELLO: содержит heartbeat_interval
  4. Отправка opcode 2 IDENTIFY: содержит token, intents, properties
  5. Начало цикла心跳: отправка opcode 1 Heartbeat с интервалом heartbeat_interval
  6. Получение opcode 0 Dispatch: событие распределения (t=имя события, s=номер, d=данные)
  7. Получение opcode 11 Heartbeat ACK: подтверждение心跳

Описание Opcode

Opcode Название Направление Описание
0 Dispatch Получение Распределение событий (с полями t, s, d)
1 Heartbeat Отправка/Получение 心跳 (содержит последний seq)
2 Identify Отправка Аутентификация
6 Resume Отправка Восстановление сессии
7 Reconnect Получение Сервер требует переподключения
9 Invalid Session Получение Недействительная сессия
10 Hello Получение Приветствие подключения (с heartbeat_interval)
11 Heartbeat ACK Получение Подтверждение心跳

Переподключение и RESUME

Механизм心跳

Примеры использования

Обработка сообщений в канале

from ErisPulse.Core.Event import message
from ErisPulse import sdk

discord = sdk.adapter.get("discord")

@message.on_message()
async def handle_group_msg(event):
    if event.get("platform") != "discord":
        return

    text = event.get_text()
    channel_id = event.get("group_id")

    if text == "hello":
        await discord.Send.To("group", channel_id).Text("Hello!")

Обработка личных сообщений

@message.on_message()
async def handle_private_msg(event):
    if event.get("platform") != "discord":
        return
    if not event.is_dm():
        return

    text = event.get_text()
    user_id = event.get("user_id")

    await discord.Send.To("user", user_id).Text(f"Вы сказали: {text}")

Отправка встроенного сообщения

embed = {
    "title": "Объявление сервера",
    "description": "Добро пожаловать в Discord-адаптер ErisPulse",
    "color": 3447003,
    "fields": [
        {"name": "Версия", "value": "4.0.0", "inline": True},
        {"name": "Фреймворк", "value": "ErisPulse", "inline": True},
    ],
    "footer": {"text": "Powered by ErisPulse"},
    "timestamp": "2025-01-01T00:00:00.000Z",
}
await discord.Send.To("group", channel_id).Embed(embed)

Использование специфических методов Discord

@message.on_message()
async def handle(event):
    if event.get("platform") != "discord":
        return

    channel_id = event.get_channel_id()
    guild_id = event.get_guild_id()
    is_dm = event.is_dm()
    embeds = event.get_embeds()
    attachments = event.get_attachments()

    if embeds:
        await discord.Send.To("group", channel_id).Text(
            f"Получено {len(embeds)} встроенных сообщений"
        )

Обработка событий взаимодействия

from ErisPulse.Core.Event import request

@request.on_request()
async def handle_interaction(event):
    if event.get("platform") != "discord":
        return

    interaction = event.get_interaction_data()
    if interaction.get("type") == 3:  # MESSAGE_COMPONENT
        await event.reply("Кнопка была нажата!")