Функции API для Discord

Функции вызываются в блоке в поле переменных или прямо в тексте ответа через #{...}:

#{discord_add_role(message_from, '1465674567090704592')}

Идентификаторы серверов, каналов, ролей и сообщений в Discord — это длинные числа. Копировать их удобнее всего так: Настройки → Расширенные → Режим разработчика, после чего в контекстном меню любого объекта появится пункт «Копировать ID».

Подключение бота описано в статье «Как создать чат-бота в Discord».

Где взять id сообщения

Id сообщения, на которое сработал блок, лежит в переменной discord_message_id — отдельно доставать его не нужно:

#{discord_delete_message(discord_message_id)}

Если нужны данные, которых нет в готовых переменных, полный вебхук доступен в переменной discord_webhook — она заполняется, когда переменной save_webhook присвоено любое значение:

data = discord_webhook["data"]

msg_id = data["id"]

result = discord_reply_to_message(msg_id, "Это ответ на сообщение")

Переменные, которые появляются сами

Заполняются при каждом событии, настраивать их не нужно.

Переменная Что внутри Пример
guild_id id сервера 1465674567090704591
discord_event тип события одним словом message
discord_message_id id сообщения, с префиксом mid mid1465674569095319625
message_from id автора события, с префиксом uid uid413984787162726410
from_username логин автора в Discord 00rei
from_name как автор подписан в чате Рус
username логин, для личных сообщений боту 00rei
is_bot 1, если автор события — другой бот 0
nickname ник на сервере, пусто если не задан Модератор
roles список id ролей автора ["1465674567090704592"]
is_admin 1 — администратор или владелец сервера 1
reply_from id автора сообщения, на которое ответили uid493121376652230668
reply_from_username его логин _deikin
reply_from_name его отображаемое имя Рус
reply_to_bot 1, если ответили боту 0
reply_message_id id сообщения, на которое ответили mid1534837349219958804
reply_text текст сообщения, на которое ответили кто дежурит сегодня?

Префиксы uid, cid и mid — часть значения. Передавать переменные в функции нужно как есть, ничего отрезать не надо.

from_name против from_username. В from_name лежит то имя, которым к человеку обращаются в чате: ник на сервере, если он задан, иначе отображаемое имя аккаунта, иначе логин. Именно его стоит подставлять в приветствия — from_username часто выглядит как _deikin или 00rei.

Группа reply_* заполняется, только когда сообщение является ответом на другое. На обычном сообщении все они очищаются, поэтому проверка:

#{reply_from != ''}

надёжно отличает ответ от обычного сообщения.

nickname, roles и is_admin относятся к автору текущего события. На реакциях Discord этих данных не присылает, поэтому проверять администратора надо на сообщении или слэш-команде.

Текст входящего сообщения лежит в стандартной переменной question, как и в остальных каналах.

События

Кроме обычных сообщений в воронку приходят служебные события. Их текст попадает в question, так что ловить их можно обычным текстовым условием.

discord_event Текст в question Когда
message текст сообщения участник написал
message_edit новый текст сообщения сообщение отредактировали
interaction /warn @user спам вызвали слэш-команду или нажали кнопку
reaction_add new_like ❤️ uid413984787162726410 поставили реакцию
reaction_remove reaction_remove ❤️ uid413984787162726410 сняли реакцию
message_delete message_delete mid1465674569095319625 удалили сообщение
messages_delete_bulk messages_delete_bulk 12 удалили несколько сообщений
member_join member_join uid413984787162726410 участник зашёл на сервер
member_leave member_leave uid413984787162726410 вышел
member_update member_update uid413984787162726410 сменил ник или роли
member_ban member_ban uid413984787162726410 забанен
member_unban member_unban uid413984787162726410 разбанен

У кастомной реакции вместо эмодзи будет её id:

new_like beer:1479419477396291696 uid413984787162726410

Подробнее — в разделе про реакции.

Если блок должен срабатывать только на живые сообщения участников, добавьте в условие:

discord_event == 'message'

Это отсечёт все служебные события разом. Проверять по тексту ненадёжно: участник может написать member_join руками.

member_update приходит на любое изменение участника, в том числе на роль, которую выдал сам бот. Блок, который реагирует на member_update и выдаёт роль, зациклится — такие условия всегда стоит ограничивать.

Сообщения

Функция Что делает
discord_send_message(channel_id, text) написать в произвольный канал
discord_send_dm(user_id, text) написать участнику в личные сообщения
discord_reply_to_message(message_id, text) ответить на сообщение
discord_edit_message(message_id, text) изменить своё сообщение
discord_delete_message(message_id) удалить сообщение
discord_bulk_delete_messages(channel_id, message_ids) удалить несколько сообщений сразу
discord_get_message(channel_id, message_id) прочитать сообщение
discord_pin_message(message_id) закрепить
discord_unpin_message(message_id) открепить

Ограничения Discord: ограничения по времени на правку и удаление своих сообщений нет; массовое удаление работает только для сообщений не старше 14 дней, за раз от 2 до 100 штук.

Реакции

Функция Что делает
discord_send_reaction(message_id, reaction) поставить реакцию
discord_delete_reaction(message_id, reaction, user_id) снять реакцию; без user_id снимается реакция бота

В параметр reaction передаётся либо один эмодзи, например ❤️, либо id кастомного эмодзи сервера.

Где взять id кастомной реакции

Поставьте нужную кастомную реакцию на любое сообщение в канале — в чат придёт коллбек вида:

new_like beer:1479419477396291696 uid413984787162726410

Здесь beer:1479419477396291696 и есть id реакции. Его можно скопировать и подставлять в функции работы с реакциями:

#{discord_send_reaction(discord_message_id, 'beer:1479419477396291696')}

Обычные эмодзи приходят в коллбеке как есть:

new_like ❤️ uid413984787162726410

где uid413984787162726410 — id участника, поставившего реакцию.

Модерация

Функция Что делает
discord_timeout_member(user_id, seconds) мьют на указанное количество секунд, максимум 28 суток
discord_remove_timeout(user_id) снять мьют досрочно
discord_kick_member(user_id) исключить с сервера, вернуться можно по приглашению
discord_ban_member(user_id, delete_message_seconds) забанить; вторым аргументом — за сколько секунд удалить его сообщения, максимум 7 суток
discord_unban_member(user_id) разбанить

Модерировать участника, чья роль стоит выше роли бота, Discord не позволит. Владельца сервера — тоже.

Роли и участники

Функция Что делает
discord_add_role(user_id, role_id) выдать роль
discord_remove_role(user_id, role_id) снять роль
discord_get_roles() список ролей сервера с их id
discord_get_member(user_id) данные участника: ник, роли, дата входа
discord_set_nickname(user_id, nickname) сменить ник на сервере

Роль бота должна стоять выше выдаваемой. Роль @everyone и роли, которыми управляют интеграции, в том числе роли других ботов, выдать нельзя.

Каналы и тикеты

Функция Что делает
discord_create_channel(name, type, parent_id, permission_overwrites) создать канал
discord_delete_channel(channel_id) удалить канал
discord_set_channel_permission(channel_id, target_id, allow, deny, type) выдать или запретить права на канал
discord_create_invite(channel_id, max_age, max_uses) ссылка-приглашение
discord_get_invites() список приглашений сервера

У discord_create_channel тип по умолчанию 0 — текстовый канал; 2 — голосовой, 4 — категория. В parent_id можно передать id категории, чтобы канал появился внутри неё.

У discord_set_channel_permission последний аргумент — кому выдаются права: 1 — участнику, 0 — роли. В allow и deny передаются числа:

Число Право
1024 видеть канал
2048 писать в канал
3072 видеть и писать
65536 читать историю

У discord_create_invite время жизни ссылки задаётся в секундах (86400 — сутки), max_uses со значением 0 означает «без ограничения».

Слэш-команды

Функция Что делает
discord_get_commands() список команд, зарегистрированных на сервере
discord_set_commands(commands) заменить набор команд целиком

discord_set_commands принимает список команд:

#{discord_set_commands('[
  {"name": "rules", "description": "Показать правила сервера"},
  {
    "name": "warn",
    "description": "Выдать предупреждение",
    "options": [
      {"type": 6, "name": "user", "description": "Кому", "required": true},
      {"type": 3, "name": "reason", "description": "Причина", "required": false}
    ]
  }
]')}

Требования Discord: name — строчными буквами, без пробелов, от 1 до 32 символов; description обязательно, от 1 до 100 символов.

Типы опций:

  • 3 — строка;
  • 4 — целое число;
  • 5 — да/нет;
  • 6 — участник;
  • 7 — канал;
  • 8 — роль.

Обязательные опции должны идти раньше необязательных. Пустой список удаляет все команды бота на сервере.

Вызов команды приходит в воронку строкой вида:

/warn @user спам

То есть имя команды и значения опций через пробел. Ловится обычным текстовым условием.

Отдельная функция для кнопок не нужна: кнопки настраиваются у обычного блока ответа, а нажатие приходит так же, как слэш-команда, — в тексте будет значение кнопки.

Очки и рейтинг

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

Функция Что делает
discord_add_thanks_score(value) начислить очки автору цитируемого сообщения
discord_add_thanks_score_for_answer(value) начислить тому, кто ответил
discord_minus_thanks_score(value) снять очки
discord_get_score(user_id) очки участника числом; без аргумента — автор события
discord_get_level(user_id, points_per_level) уровень участника; порог по умолчанию 100 очков
discord_get_user_info(user_id) очки, место в рейтинге и имя одним объектом
discord_get_top(count, shift, humanize, delimiter) лидерборд

У discord_get_top аргумент count — сколько строк вывести, shift — со скольких пропустить для листания, humanize со значением true вернёт готовый текст, delimiter — чем разделять имя и очки.

В условии блока очки надо сравнивать через discord_get_score — эта функция возвращает число, с которым сравнение работает как ожидается.

Примеры

Приветствие новичка в личные сообщения

Условие блока — member_join, в поле переменных:

discord_send_dm(message_from, 'Привет, #{from_name}! Загляни в правила в закрепе.')

Удалить сообщение со стоп-словом и выдать мьют на сутки

Условие — список стоп-слов, дополнительное условие is_admin != 1:

discord_delete_message(discord_message_id)

discord_timeout_member(message_from, 86400)

Роль за реакцию под конкретным сообщением

Условие — new_like 🍕, дополнительное условие:

contains(discord_message_id, '1534927170965602324')

Код:

discord_add_role(message_from, '1465674567090704592')

Личный канал-тикет по кнопке

ticket = discord_create_channel('ticket-' + from_username)

ticket_channel = get(get(ticket, 'data'), 'id')

discord_set_channel_permission(ticket_channel, guild_id, None, 1024, 0)

discord_set_channel_permission(ticket_channel, message_from, 3072, None, 1)

discord_send_message(ticket_channel, 'Опишите проблему одним сообщением.')

Первая строка с правами закрывает канал от всех (guild_id здесь — это роль @everyone), вторая открывает его автору обращения.

Очки за благодарность и роль за уровень

Условие блока — слова спасибо;спс;благодарю, дополнительное условие:

reply_from != '' and reply_from != message_from and reply_to_bot != 1

Код:

discord_add_thanks_score(1)

if (discord_get_level(reply_from) >= 1) {
  discord_add_role(reply_from, '1465674567090704592')
}

Проверка reply_from != message_from не даёт начислять очки самому себе, reply_to_bot != 1 — боту.

Показать свои очки по команде

Условие — /xp:

points = discord_get_score()

lvl = discord_get_level()

В тексте ответа:

#{from_name}, у тебя #{points} XP · уровень #{lvl}

Лидерборд по команде

Условие — /top, текст ответа:

🏆 Топ по XP:

#{discord_get_top(10, 0, true, ' — ')}