Add RSVP role synchronization and localization support for Discord
This commit introduces functionality for managing event-specific RSVP roles in Discord, including roles for "Registered", "Going", "Maybe", and "Not Going". The `RoleWorker` has been enhanced to handle these roles based on user registrations, with localization support for role names in Russian and English. Additionally, the database schema has been updated to accommodate new role types and actions, and the service layer has been modified to trigger role synchronization upon relevant event updates. Tests have been added to ensure the correct behavior of the new RSVP handling logic.
This commit is contained in:
@@ -8,6 +8,7 @@ Admin UI содержит пошаговый workflow и roster editor с same-r
|
||||
Добавлена роль Moderator: она имеет все операционные права Admin, но управление списком модераторов доступно только Admin. До состояния Live workflow можно откатить на один этап назад.
|
||||
Добавлен Discord-анонс нового микса: после успешного создания Event backend через Bot REST API публикует локализованный embed и кнопку регистрации. При создании staff может оставить включённой галочку уведомления `@everyone` или отправить тихий анонс без пинга. Ошибка Discord логируется, но не отменяет создание события; без bot token и channel ID интеграция отключена.
|
||||
Добавлен PostgreSQL-backed Discord role worker. После подтверждения составов он создаёт и выдаёт роли по актуальным Team.Name, Captain и slot Tank/Damage/Support, учитывает live-переименование и аварийную замену, а при завершении/отмене/удалении/откате удаляет временные роли. Повтор jobs идемпотентен; guest и отсутствующие в guild игроки сохраняются как предупреждения и не блокируют микс.
|
||||
При любом RSVP тот же worker создаёт event-specific роли «Зарегистрирован», «Идёт», «Возможно», «Не идёт», выдаёт общую роль ответа и ровно один текущий статус, обновляет названия при rename Event и снимает назначения после удаления RSVP. Registration close роли не удаляет; общий event teardown очищает их вместе с team/captain roles.
|
||||
|
||||
## Подтверждённые требования
|
||||
|
||||
@@ -35,6 +36,7 @@ Admin UI содержит пошаговый workflow и roster editor с same-r
|
||||
- карточки отменённых событий отображаются красными, завершённых — зелёными, активных — розовыми с меткой LIVE.
|
||||
- новый микс автоматически анонсируется в настроенном Discord-канале со ссылкой на регистрацию; `@everyone` можно отключить при создании.
|
||||
- подтверждённые составы автоматически проецируются в управляемые Discord-роли и очищаются по завершении их жизненного цикла.
|
||||
- явные RSVP автоматически проецируются в локализованные event-specific Discord-роли ответа и статуса.
|
||||
|
||||
## Исходный регламент
|
||||
|
||||
@@ -81,6 +83,6 @@ Admin UI содержит пошаговый workflow и roster editor с same-r
|
||||
|
||||
## Ближайший следующий шаг
|
||||
|
||||
Проверить миграции `006_event_workflow.sql` и `011_discord_role_sync.sql` с реальной PostgreSQL (`TEST_DATABASE_URL`), затем на staging проверить анонс, подтверждение roster, rename/emergency substitution и cleanup Discord-ролей перед первым production-миксом.
|
||||
Проверить миграции `006_event_workflow.sql`, `011_discord_role_sync.sql` и `012_discord_rsvp_roles.sql` с реальной PostgreSQL (`TEST_DATABASE_URL`), затем на staging проверить RSVP transitions, анонс, подтверждение roster, rename/emergency substitution и cleanup Discord-ролей перед первым production-миксом.
|
||||
|
||||
Публичная вкладка FAQ описывает регистрацию, балансировку, полномочия капитанов, выбор карт, баны героев и подсчёт Bo3.
|
||||
|
||||
@@ -122,6 +122,8 @@ Application-слой управляет единым versioned workflow собы
|
||||
|
||||
Очередь использует `FOR UPDATE SKIP LOCKED`, timeout и retry/backoff для 429/5xx. Частичная недоступность Discord, guest или отсутствующий в guild пользователь не откатывают доменную команду; предупреждение сохраняется в job. При отмене, завершении, удалении или откате подтверждения event-specific team/captain roles удаляются. Общие ролевые назначения пересчитываются по всем другим активным миксам, поэтому параллельные события не снимают нужную роль. Role worker включается только при наличии `DISCORD_GUILD_ID` и не требует Gateway intents.
|
||||
|
||||
Тот же worker ведёт event-specific RSVP-роли независимо от наличия roster: `registered` обозначает явный ответ, а `going` / `maybe` / `not_going` взаимоисключающи и следуют текущей записи RSVP. Изменение RSVP, удаление участника и переименование Event ставят отдельный job. Roster reconcile и RSVP reconcile владеют разными role kinds и не удаляют роли друг друга; общий teardown очищает все event-specific роли.
|
||||
|
||||
### Капитаны
|
||||
|
||||
Капитан — назначение внутри конкретной команды, а не глобальная роль аккаунта. Admin может назначить или заменить капитана только участником этой команды. Только текущий капитан выполняет командные действия драфта; Admin имеет аварийное право выполнить действие с обязательной записью в аудит.
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
Team/captain roles принадлежат конкретному Event и удаляются при отмене, завершении, удалении или возврате к редактированию roster. Tank/Damage/Support общие для guild: после cleanup их участники пересчитываются по всем оставшимся активным событиям. Guest и пользователь, отсутствующий в guild, не блокируют подтверждение состава и фиксируются как предупреждение интеграции.
|
||||
|
||||
Для каждого Event бот также поддерживает четыре временные RSVP-роли: общую `Зарегистрирован: {Event.Name}` для любого явного ответа и взаимоисключающие `Идёт`, `Возможно`, `Не идёт`. Изменение EventRegistration атомарно меняет desired status-role; удаление регистрации снимает все RSVP-назначения. Эти роли сохраняются после закрытия регистрации и удаляются вместе с другими event-specific ролями при завершении, отмене или удалении Event.
|
||||
|
||||
### Жизненный цикл события
|
||||
|
||||
Событие проходит серверно контролируемые состояния:
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
- статистика игроков и команд;
|
||||
- повторная жеребьёвка с защитой от одинаковых составов;
|
||||
- [x] Discord-анонс нового микса с `@everyone` и ссылкой на регистрацию;
|
||||
- [x] event-specific Discord-роли ответа и статусов Going/Maybe/NotGoing;
|
||||
- обновление анонса, напоминания, публикация составов и результатов;
|
||||
- [x] идемпотентная синхронизация временных Discord team/captain и Tank/Damage/Support ролей;
|
||||
- создание и очистка временных командных голосовых каналов;
|
||||
|
||||
Reference in New Issue
Block a user