From 8c1e7991cda62f6b3ed13bef7d0603d733f9a6a9 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Thu, 7 May 2026 10:22:35 +0300 Subject: [PATCH] feat(#13): add calendar subscription link to Telegram export --- .../ExportCalendar/ExportCalendarHandler.cs | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/GmRelay.Bot/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs b/src/GmRelay.Bot/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs index 5744159..57524e7 100644 --- a/src/GmRelay.Bot/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs +++ b/src/GmRelay.Bot/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs @@ -1,9 +1,11 @@ using System.Text; using Dapper; using GmRelay.Shared.Domain; +using Microsoft.Extensions.Configuration; using Npgsql; using Telegram.Bot; using Telegram.Bot.Types; +using Telegram.Bot.Types.ReplyMarkups; namespace GmRelay.Bot.Features.Sessions.ExportCalendar; @@ -11,7 +13,8 @@ internal sealed record CalendarSessionDto(Guid Id, string Title, DateTime Schedu public sealed class ExportCalendarHandler( NpgsqlDataSource dataSource, - ITelegramBotClient botClient) + ITelegramBotClient botClient, + IConfiguration configuration) { public async Task HandleAsync(Message message, CancellationToken cancellationToken) { @@ -64,11 +67,45 @@ public sealed class ExportCalendarHandler( var inputFile = InputFile.FromStream(stream, "schedule.ics"); + // Create calendar subscription + string? subscriptionUrl = null; + var baseUrl = configuration["Web:BaseUrl"]; + var senderId = message.From?.Id; + if (!string.IsNullOrWhiteSpace(baseUrl) && senderId.HasValue) + { + try + { + var token = Guid.NewGuid().ToString("N"); + var groupId = await connection.QueryFirstOrDefaultAsync( + @"SELECT id FROM game_groups WHERE telegram_chat_id = @ChatId", + new { ChatId = message.Chat.Id }); + + await connection.ExecuteAsync( + @"INSERT INTO calendar_subscriptions (id, token, user_telegram_id, group_id, filter_type, created_at, expires_at) + VALUES (gen_random_uuid(), @token, @userTelegramId, @groupId, @filterType, now(), NULL)", + new { token, userTelegramId = senderId.Value, groupId, filterType = (int)CalendarSubscriptionFilter.SpecificGroup }); + + subscriptionUrl = $"{baseUrl.TrimEnd('/')}/calendar/{token}.ics"; + } + catch + { + // Non-critical: if subscription creation fails, still send the file + } + } + + var replyMarkup = subscriptionUrl is not null + ? new InlineKeyboardMarkup(new[] + { + new[] { InlineKeyboardButton.WithUrl("🔗 Подписаться на календарь", subscriptionUrl) } + }) + : null; + await botClient.SendDocument( chatId: message.Chat.Id, document: inputFile, caption: "📅 Ваш календарь игр!\nОткройте файл на устройстве, чтобы добавить события в свой календарь.", parseMode: Telegram.Bot.Types.Enums.ParseMode.Html, + replyMarkup: replyMarkup, messageThreadId: message.MessageThreadId, cancellationToken: cancellationToken); }