# 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.
