- Rewrite Profile.razor to use .page-container, .glass-card, .gm-alert,
.btn-gm, .status-badge, .empty-state and other standard design system classes
- Replace custom unstyled markup with breadcrumb, page-header, skeleton loaders
- Add .identity-list styles to app.css for linked accounts section
- Unify visual language with Home, Templates and GroupDetails pages
Заменен Navigation.Uri.Contains() на QueryHelpers.ParseQuery
для корректного определения параметра register без ложных
срабатываний на подстроки (например, register=10).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- PublicSession.razor: добавлена обработка ?register=1, AuthStateProvider,
TryGetPlatformIdentity, кнопки записи для авторизованных/неавторизованных
пользователей, отображение результата регистрации
- CreateSessionHandler: добавлен cover_image_url в INSERT SQL
- DiscordProjectStructureTests: версия 3.4.0 во всех проверках
- README.md: актуальная версия v3.4.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add publication settings for clubs and sessions, read-only public club/session pages, dashboard controls, privacy-focused public queries, docs, and tests.
Bump version to 3.3.0
PR #106 extracted DeleteSessionHandler and ListSessionsHandler to GmRelay.Shared,
but forgot to register the shared implementations in Program.cs. This caused
an InvalidOperationException at startup on Native AOT builds because the Bot
wrappers could not resolve their shared dependencies.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Create a Telegram forum topic when Web creates a batch from a campaign template, persist thread ownership on the generated sessions, and send the batch schedule into that topic.
Bump version -> 3.1.1
- Migrated all core domain SQL from telegram_* columns to platform + external_*
- Added V024/V025 migrations with backfill and deprecation comments
- Removed all COALESCE(external_*, telegram_*) fallbacks
- Replaced gm_telegram_id join with group_managers query in HandleRsvpHandler
- Updated Bot, Web, DiscordBot, and Shared handlers
- Bumped version to 3.1.0
CI run #265 passed (289 tests, 0 warnings, 0 vulnerabilities)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Добавлены миграции V024 (backfill + deprecation comments + calendar_subscriptions platform identity) и V025 (backfill proposed_by_external_user_id)
- Все Bot handlers переведены с telegram_id/chat_id на platform + external_*
- Shared handlers очищены от COALESCE fallback с telegram_* колонками
- DiscordBot очищен от COALESCE fallback
- Web SessionService и CalendarSubscriptionService переведены на external_*
- HandleRsvpHandler: убран legacy UNION с gm_telegram_id, теперь только group_managers
- RescheduleVotingFinalizer: переведен на external_username/external_user_id
- Tests: добавлены asserts для V024/V025
- Версия обновлена до 3.1.0
Bump version → 3.1.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- SessionSchedulerService now backs off for 15 minutes after any
handler failure (confirmation, one-hour reminder, join link),
preventing infinite retry loops on Discord 403 Missing Access.
- Added per-session ConcurrentDictionary backoff tracking with
automatic cleanup on success.
- Enhanced DiscordPlatformMessenger logging for SendConfirmation
and SendJoinLink to aid permission diagnostics.
- Added 3 regression tests for backoff behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DiscordNewSessionHandler.ParseTimeInput used DateTimeStyles.AssumeUniversal,
which interpreted user input as UTC. A user entering 15:00 got a session
scheduled at 18:00 MSK after rendering. Align with Telegram behavior by
treating input as Moscow time and converting to UTC before storage.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
V023 migration drops NOT NULL constraints on:
- game_groups.telegram_chat_id
- game_groups.gm_telegram_id
- players.telegram_id
This allows Discord (and future platforms) to create players and
game_groups without legacy Telegram identifiers.
Bump version → 3.0.10
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
GmRelay.Shared references Dapper.AOT with PrivateAssets=all, which
prevents the runtime DLL from flowing to downstream projects. Telegram
bot works because it explicitly references Dapper.AOT directly, but
Discord bot did not — causing FileNotFoundException for Dapper.AOT
at runtime, breaking the scheduler and slash commands.
- Add Dapper.AOT 1.0.48 to GmRelay.DiscordBot.csproj
- Add regression test: DiscordWorkerProject_ShouldExist asserts
Dapper.AOT is present in the DiscordBot csproj
- Bump version → 3.0.9
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>