Tady
Публичный Discord-бот для сообществ: 2500+ серверов и 260 000+ пользователей в пике. Собственный менеджер шардов на PHP, Redis для активного состояния, интерфейс на двух языках.

Стек
- PHP
- DiscordPHP
- MySQL
- Redis
- JavaScript
- discord.js
- Node.js
Задача
Сообществам, в которых я общался, регулярно не хватало одних и тех же функций: делить участников на команды случайным образом, создавать каналы-считалки, проводить розыгрыши на русском языке с нужными условиями и удобнее модерировать сервер. Существующие боты закрывали только отдельные сценарии, а собрать весь нужный набор функций даже из нескольких решений не получалось. Поэтому Tady начинался как приватный бот для нескольких Discord-серверов.
Решение
Когда стало понятно, что те же сценарии нужны и другим сообществам, бот стал публичным. Сотню серверов он набрал быстро, и с этим порогом пришла обязательная верификация Discord. Отдельным процессом шло ревью на привилегированные интенты, без которых часть команд не работает. По мере роста я адаптировал архитектуру под масштаб: шардирование, Redis для активного состояния и мультиязычный интерфейс.
Архитектура
Ключевые технические решения
- Менеджер шардов: подключение к Discord разделено на несколько Gateway-соединений, и каждое работает в отдельном PHP-процессе. DiscordPHP принимает номер шарда, но процессами не управляет, поэтому в проекте реализован собственный менеджер их запуска, контроля и перезапуска.
- Redis как слой активного состояния, а база — как источник истины: при перезапуске бот поднимает состояние из базы, а новые розыгрыши пишет сразу в оба места.
- Язык берётся из настроек Discord самого пользователя, английский — запасной вариант: сервер с русскоязычной аудиторией не заставляет никого переключаться вручную.
- Обработка ошибок различает источник проблемы: не хватает прав у пользователя или у бота; название права показывается на языке того, кто вызвал команду.
- Привилегированные интенты сокращены до необходимого: на верификации запрашивались все три, но Presence больше не нужен, и в актуальном ревью остаются только Members и Message Content.
Масштаб и шардирование
При росте до 2500+ серверов проект перешёл на обязательное для такого масштаба шардирование Discord.
Шард в Discord — это отдельное соединение с Gateway. Гильдии распределяются между шардами по формуле от их ID, при этом один шард поддерживает максимум 2500 серверов. DiscordPHP поддерживает параметры шардирования, но не предоставляет готового менеджера shard-процессов, поэтому для Tady был реализован собственный: каждый шард запускался в отдельном PHP-процессе, а запуск, контроль и перезапуск были автоматизированы. Состояние между процессами оставалось общим: Redis хранил активные розыгрыши и таймеры, а MySQL служил источником истины и сохранял постоянное состояние. При перезапуске shard-процесса активное состояние не терялось, а восстанавливалось из MySQL в Redis: розыгрыши, LFG, считалки и другие сохраняемые сценарии.
В ходе развития проекта была реализована отдельная версия на Node.js и discord.js. Позже развитие этой ветки было остановлено, а текущий production остался на PHP и DiscordPHP.
Мультиязычность
Бот поддерживает русский и английский языки. Ответы, подписи кнопок и справочные сообщения автоматически подстраиваются под язык, выбранный пользователем в интерфейсе Discord. Если выбранный язык не поддерживается, используется английский вариант по умолчанию.

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

Формат длительности
Длительность задаётся текстом, без ручного перевода в секунды или минуты. Например, запись 1д 3ч 12м 10с корректно интерпретируется как 1 день, 3 часа, 12 минут и 10 секунд. Этот формат работает во всех командах, где нужно указать срок.

Розыгрыши
Команда /giveaway запускает розыгрыш, который сам завершается по таймеру. Продолжительность задаётся в том же формате, что и в других командах. После запуска бот отслеживает оставшееся время, автоматически подводит итоги и случайным образом выбирает одного или нескольких победителей из числа участников. Автор розыгрыша может просматривать свои активные розыгрыши, завершать их досрочно и при необходимости перевыбирать победителей.

Помощь и подсказки
У каждой команды есть краткое описание, инструкция и примеры: посмотреть их можно через /help (список команд) или /help <название команды> (подробности по конкретной). Такой ответ виден только тому, кто его запросил, и не засоряет канал.

Сервер поддержки
У бота есть сервер поддержки, где пользователи получают помощь, находят ответы на частые вопросы и следят за новостями проекта. Бот никогда не делает рассылки в личных сообщениях или на серверах пользователей.

Утилиты и развлечения
Помимо основных сценариев у Tady есть небольшие команды для повседневной жизни сообщества: /teams делит участников на команды случайным образом, /translit переводит кириллицу в латиницу для никнеймов, /info и /avatar показывают данные аккаунта, а /counter создаёт каналы-считалки. Отдельно стоит /lfg, сбор на игру: бот публикует запись с местами и временем, участники присоединяются кнопкой, и когда группа набрана, он объявляет об этом сам.

Результаты
- Прошёл верификацию Discord и ревью на привилегированные интенты, без которых команды не работают на большом числе серверов.
- Вырос из приватного бота для нескольких сообществ в публичный проект, который работает и поддерживается до сих пор.
- Шардирование и общее состояние позволили масштабировать бота без привязки всей нагрузки к одному Gateway-соединению или процессу.
Метрики
- Discord-серверов в пике
- 2500+
- пользователей в пике
- 260 000+
Факты
- Из-за бага в системе тикетов Discord верификация заняла 4 месяца, и всё это время платформа не давала пользователям приглашать бота на свои серверы.