Reaction roles — самостоятельная выдача ролей через реакции
Каждый новый игрок в личку модератору: «дайте роль Rust», «а как получить пинг по вайпам», «хочу роль стримера» — знакомая картина для любого растущего Discord-комьюнити. Reaction roles закрывают это раз и навсегда: игрок ставит реакцию под сообщением с описанием ролей и мгновенно получает нужную сам, без участия человека. Разберём, как это настроить — через бота и без него, что может пойти не так и как не превратить канал с ролями в кашу.
Содержание
- Как это работает технически
- Вариант 1: Carl-bot — бесплатно и без кода
- Вариант 2: YAGPDB — гибче, но чуть сложнее интерфейс
- Вариант 3: нативный Onboarding — без ботов вообще
- Своя реализация на discord.js — когда нужна кастомная логика
- Грабли, на которые наступают почти все
- Разграничение прав: publicroles vs privileged 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 в игровых комьюнити: функция полностью бесплатна, без премиум-стены, настраивается через веб-дашборд без единой команды в чате.
Порядок настройки:
- Пригласите бота с правами Manage Roles и Manage Messages, поднимите его роль в иерархии сервера выше всех ролей, которые будете раздавать (перетащить в Server Settings → Roles).
- Зайдите на dashboard.carl.gg, выберите сервер → Reaction Roles.
- Создайте новую группу — либо на существующее сообщение (вставляете ID сообщения, зажав Developer Mode в Discord и скопировав «Copy Message ID»), либо попросите бота сам опубликовать новый эмбед командой:
!rr create
- В интерфейсе дашборда добавляете пары эмодзи → роль. Можно использовать стандартные эмодзи Discord (🎮, ⚔️, 🛠️) или свои кастомные с сервера.
- Настраиваете режим: 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 минут через дашборд).