MAATRIX GAMES / Блог / Reaction roles — самостоятельная выдача ролей через реакции

Reaction roles — самостоятельная выдача ролей через реакции

MAATRIX GAMES

Каждый новый игрок в личку модератору: «дайте роль Rust», «а как получить пинг по вайпам», «хочу роль стримера» — знакомая картина для любого растущего Discord-комьюнити. Reaction roles закрывают это раз и навсегда: игрок ставит реакцию под сообщением с описанием ролей и мгновенно получает нужную сам, без участия человека. Разберём, как это настроить — через бота и без него, что может пойти не так и как не превратить канал с ролями в кашу.

Как это работает технически

Идея простая: в канале висит сообщение (обычно эмбед со списком ролей и эмодзи напротив каждой). Бот подписан на события реакций — MESSAGE_REACTION_ADD и MESSAGE_REACTION_REMOVE — и держит у себя таблицу соответствий «ID сообщения → эмодзи → ID роли». Когда пользователь ставит реакцию, Discord присылает боту событие, бот сверяет его с таблицей и, если совпадение есть, вызывает Discord API для выдачи роли конкретному участнику. Снял реакцию — роль забирается тем же путём.

Сам Discord нативной функции «эмодзи на сообщении = роль» не даёт — это исторически территория ботов. Но за последние пару лет Discord добавил свою альтернативу без ботов — Onboarding с выбором ролей на входе (о нём ниже). Так что путей на самом деле два: классические reaction roles через бота (гибче, работают в любом канале в любой момент) и нативный набор ролей через настройки сервера (проще, но с ограничениями).

Важный технический момент, который ломает reaction roles чаще всего: у бота должно быть право Manage Roles, и его собственная роль в иерархии сервера обязана стоять выше всех ролей, которые он должен выдавать. Discord API запрещает боту трогать роли, расположенные выше его собственной по списку в Server Settings → Roles — это не баг настройки, а осознанное ограничение платформы против эскалации прав.

Вариант 1: Carl-bot — бесплатно и без кода

Carl-bot (carl.gg) — самый популярный выбор для reaction roles в игровых комьюнити: функция полностью бесплатна, без премиум-стены, настраивается через веб-дашборд без единой команды в чате.

Порядок настройки:

  1. Пригласите бота с правами Manage Roles и Manage Messages, поднимите его роль в иерархии сервера выше всех ролей, которые будете раздавать (перетащить в Server Settings → Roles).
  2. Зайдите на dashboard.carl.gg, выберите сервер → Reaction Roles.
  3. Создайте новую группу — либо на существующее сообщение (вставляете ID сообщения, зажав Developer Mode в Discord и скопировав «Copy Message ID»), либо попросите бота сам опубликовать новый эмбед командой:
!rr create
  1. В интерфейсе дашборда добавляете пары эмодзи → роль. Можно использовать стандартные эмодзи Discord (🎮, ⚔️, 🛠️) или свои кастомные с сервера.
  2. Настраиваете режим: Normal (можно набрать сколько угодно ролей из группы), Unique (только одна роль из группы — если ставишь вторую реакцию, первая автоматически снимается) или Verify (реакция подтверждает согласие с правилами и снимает саму реакцию сразу после выдачи роли).

Режим Unique обычно нужен для взаимоисключающих ролей — например, «Играю на EU» / «Играю на RU», где две одновременно не имеют смысла. Для ролей по интересам (любимая игра, часовой пояс, роль «ищу тиммейтов») подойдёт Normal.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Вариант 2: YAGPDB — гибче, но чуть сложнее интерфейс

YAGPDB (yagpdb.xyz) — ещё один полностью бесплатный бот с reaction roles, исторически популярный в крупных RP- и MMO-комьюнити за счёт более тонких настроек (например, лимит на количество ролей на человека из одной группы, требование определённой роли для доступа к другой группе).

Настройка через веб-панель: Control Panel → Reaction Roles → добавить сообщение по ID → привязать эмодзи к ролям. Отличие от Carl-bot — YAGPDB позволяет требовать роль-предохранитель (require role), то есть реакция сработает, только если у пользователя уже есть, скажем, роль «Верифицирован», выданная через whitelist-процесс. Это удобно, если вы уже гоняете верификацию через Discord-интеграцию для RP-сервера — сначала тикет и подтверждение, потом уже самостоятельный выбор игровых ролей.

Вариант 3: нативный Onboarding — без ботов вообще

Если реакции нужны исключительно для новичков на входе (выбрать язык, игру, платформу), необязательно ставить бота — Discord с 2022 года даёт встроенный Onboarding для Community-серверов (нужен включённый статус Community в Server Settings, доступен всем серверам без порога по участникам).

Путь: Server Settings → Onboarding → включить, затем:

  • Channels & Roles — выбираете набор ролей, которые предлагаются новичку прямо на входе (до попадания в основные каналы), с описанием и эмодзи для каждой.
  • Community Prompts — можно сделать многошаговый опросник вида «На чём играете?» с вариантами-ролями (Rust / Minecraft / CS2), где выбор одного или нескольких пунктов сразу назначает роль.

Плюс: ничего не ломается при апдейтах бота, не нужен аптайм стороннего сервиса. Минус: это именно приветственный флоу для новых участников — быстро добавить новую роль в уже устоявшийся канал «выбери роли» так не получится, придётся лезть обратно в настройки Onboarding, и старые участники такой промпт повторно не увидят (разве что явно откроют Server Guide). Для постоянно живущего канала «роли по интересам», который все могут пересмотреть в любой момент, реакции через бота удобнее.

Своя реализация на discord.js — когда нужна кастомная логика

Готовые боты закрывают 90% случаев, но если нужно, например, синхронизировать роль с внешней БД или ограничить выдачу роли только донатерам определённого тира, проще дописать обработчик в собственного бота (если он уже крутится — см. статью про базовую установку Discord-бота).

Минимальный рабочий пример на discord.js v14 — важно включить partials, иначе события по некэшированным сообщениям (например, после рестарта бота) не долетят:

const { Client, GatewayIntentBits, Partials } = require('discord.js');

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessageReactions,
    GatewayIntentBits.GuildMembers,
  ],
  partials: [Partials.Message, Partials.Channel, Partials.Reaction],
});

const REACTION_ROLE_MESSAGE_ID = '1234567890123456789';
const ROLE_MAP = {
  '🎮': 'ROLE_ID_RUST',
  '⚔️': 'ROLE_ID_MINECRAFT',
  '🛠️': 'ROLE_ID_CS2',
};

client.on('messageReactionAdd', async (reaction, user) => {
  if (user.bot) return;
  if (reaction.partial) await reaction.fetch();
  if (reaction.message.id !== REACTION_ROLE_MESSAGE_ID) return;

  const roleId = ROLE_MAP[reaction.emoji.name];
  if (!roleId) return;

  const member = await reaction.message.guild.members.fetch(user.id);
  await member.roles.add(roleId).catch(console.error);
});

client.on('messageReactionRemove', async (reaction, user) => {
  if (user.bot) return;
  if (reaction.partial) await reaction.fetch();
  if (reaction.message.id !== REACTION_ROLE_MESSAGE_ID) return;

  const roleId = ROLE_MAP[reaction.emoji.name];
  if (!roleId) return;

  const member = await reaction.message.guild.members.fetch(user.id);
  await member.roles.remove(roleId).catch(console.error);
});

На Python-стороне (discord.py) логика идентична: события on_raw_reaction_add и on_raw_reaction_remove (именно raw-версии, а не обычные — они не зависят от кэша сообщений и надёжнее переживают перезапуск бота).

Грабли, на которые наступают почти все

Роль бота ниже целевой роли. Самая частая причина «реакция стоит, а роль не выдалась» — бот физически не может назначить роль выше себя по иерархии. Проверяется за 10 секунд в Server Settings → Roles: перетащите роль бота на самый верх списка ролей (выше всех ролей, которые он раздаёт, но не обязательно выше admin-ролей людей).

Лимит реакций на сообщение. Discord ограничивает число уникальных эмодзи-реакций на одном сообщении — 20 штук. Если ролей больше, разбивайте на несколько сообщений/групп («Игры», «Часовые пояса», «Пинги о вайпах») вместо одного гигантского эмбеда.

Кастомные эмодзи с других серверов. Реакция кастомным эмодзи работает только если этот эмодзи доступен участнику (загружен на сервер, где стоит реакция, либо у участника есть Nitro). Для кросс-серверной надёжности используйте стандартные Unicode-эмодзи.

Гонка при массовом рестарте бота. Если бот пересоздаёт сообщение с ролями при каждом деплое, ID сообщения меняется, и все ранее настроенные реакции у людей «висят» на старом (удалённом) сообщении, а роли новым не выдаются. Храните ID сообщения в конфиге/БД и переиспользуйте его, а не пересоздавайте с нуля.

Слишком много ролей = антипаттерн. 3-6 добровольных ролей на канал — комфортно. Когда список превращается в простыню на 40 пунктов, конверсия падает: люди либо ставят реакцию наугад, либо не ставят вообще. Лучше сгруппировать по смыслу и раскидать по нескольким тематическим сообщениям, чем собирать всё в одно.

Разграничение прав: publicroles vs privileged roles

Reaction roles должны выдавать только «мирные» роли — по игре, интересам, региону, пингам. Никогда не вешайте через реакцию роли с реальными правами (модератор, доступ к приватным каналам, whitelist на сервер) — это прямая дыра в безопасности: любой участник сервера сам себе выдаст привилегию одним кликом. Если нужна автоматическая, но контролируемая выдача роли за верификацию — это отдельный процесс (капча, тикет, проверка через RCON/базу игроков), а не свободная реакция. Структуру ролей и каналов в целом разбирали в статье про структуру Discord-сервера сообщества — reaction roles логично встраивать именно туда, в канал с публичными самообслуживаемыми ролями.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Частые вопросы

Reaction roles бесплатны в Carl-bot и YAGPDB?

Да, у обоих ботов сама функция reaction roles входит в бесплатный тариф без ограничений по числу ролей на сервере.

Можно ли выдавать роль сразу за несколько эмодзи одним кликом?

Нет, каждая пара эмодзи-роль настраивается отдельно, но можно объединить несколько пар в одну группу с режимом Unique, если роли взаимоисключающие.

Что будет, если удалить сообщение с реакциями вручную?

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

Работают ли reaction roles в ветках (threads)?

Нет, ни Carl-bot, ни YAGPDB не поддерживают reaction roles в тредах — только в обычных текстовых каналах.

Как перенести reaction roles на новый сервер при переезде комьюнити?

Настройки привязаны к конкретным ID ролей и сообщений конкретного сервера, автоматического переноса нет — придётся пересоздать группы на новом сервере вручную (обычно 10-15 минут через дашборд).