# ADR 003: Discord Integration Architecture ## Status **Accepted** — implemented in v2.6.0 (PR #87, issue #30). ## Context После Telegram-бота требовалась поддержка Discord для кросс-платформенных групп. Нужно было выбрать: 1. Библиотеку для Discord API (NetCord vs DSharpPlus vs Discord.NET). 2. Модель runtime (отдельный процесс vs тот же Worker). 3. Способ обработки интеракций (Gateway events vs HTTP interactions). ## Decision ### 1. NetCord (не DSharpPlus, не Discord.NET) - **NetCord** — лёгкий, AOT-compatible, minimal dependencies. - **DSharpPlus** — слишком тяжёлый, много зависимостей, reflection-heavy. - **Discord.NET** — несовместим с Native AOT (heavy reflection, dynamic IL). ### 2. Gateway Events внутри GmRelay.Bot - Discord Gateway worker живёт **внутри** `GmRelay.Bot` (тот же Worker Service), а не как отдельный проект. - Это упрощает DI, shared DB connection, shared `IPlatformMessenger`. - Для масштабирования можно вынести в отдельный контейнер позже. ### 3. Slash-команды через NetCord ApplicationCommandService - Регистрация глобальных slash-команд (`/newsession`, `/listsessions`) через `ApplicationCommandService`. - Команды мапятся на vertical slice handlers через `DiscordSessionInteractionModule`. ### 4. Ephemeral Replies - Все кнопки (Join/Leave/RSVP) отвечают ephemeral (`MessageFlags.Ephemeral`). - Schedule message редактируется через `DiscordPlatformMessenger` (реализация `IPlatformMessenger`). ## Consequences ### Positive - Один бинарник для Telegram + Discord. - Shared DI, shared DB pool, shared domain logic. - Native AOT совместимость. ### Negative - Gateway connection требует persistent WebSocket — при разрыве происходит reconnect. - Discord rate limits агрессивнее Telegram — нужен backoff. ## Related - Issue #30 — reschedule voting (кнопки + дедлайн). - Issue #31 — scheduler notifications через `IPlatformMessenger`. - Issue #32 — compose wiring + healthcheck. - ADR 001 — Vertical Slice, Native AOT, Aspire. - ADR 002 — Platform-Neutral Rendering.