73 lines
3.3 KiB
C#
73 lines
3.3 KiB
C#
using Dapper;
|
|
using GmRelay.Shared.Domain;
|
|
using Npgsql;
|
|
using Telegram.Bot;
|
|
using Telegram.Bot.Types;
|
|
|
|
namespace GmRelay.Bot.Features.Sessions.ListSessions;
|
|
|
|
internal sealed record SessionListItemDto(Guid Id, string Title, DateTime ScheduledAt, string Status, int? MaxPlayers, int PlayerCount, int WaitlistCount, long GmId);
|
|
|
|
public sealed class ListSessionsHandler(
|
|
NpgsqlDataSource dataSource,
|
|
ITelegramBotClient botClient)
|
|
{
|
|
public async Task HandleAsync(Message message, CancellationToken cancellationToken)
|
|
{
|
|
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
|
|
|
var sessions = await connection.QueryAsync<SessionListItemDto>(
|
|
@"SELECT s.id as Id, s.title as Title, s.scheduled_at as ScheduledAt, s.status as Status, s.max_players as MaxPlayers,
|
|
COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Active) as PlayerCount,
|
|
COUNT(sp.id) FILTER (WHERE sp.is_gm = false AND sp.registration_status = @Waitlisted) as WaitlistCount,
|
|
g.gm_telegram_id as GmId
|
|
FROM sessions s
|
|
JOIN game_groups g ON s.group_id = g.id
|
|
LEFT JOIN session_participants sp ON s.id = sp.session_id
|
|
WHERE g.telegram_chat_id = @ChatId AND s.status != @Cancelled AND s.scheduled_at > NOW()
|
|
GROUP BY s.id, s.title, s.scheduled_at, s.status, s.max_players, g.gm_telegram_id
|
|
ORDER BY s.scheduled_at ASC",
|
|
new
|
|
{
|
|
ChatId = message.Chat.Id,
|
|
Cancelled = SessionStatus.Cancelled,
|
|
Active = ParticipantRegistrationStatus.Active,
|
|
Waitlisted = ParticipantRegistrationStatus.Waitlisted
|
|
});
|
|
|
|
var sessionsList = sessions.ToList();
|
|
|
|
if (sessionsList.Count == 0)
|
|
{
|
|
await botClient.SendMessage(
|
|
chatId: message.Chat.Id,
|
|
text: "📭 В этой группе нет предстоящих игр.",
|
|
cancellationToken: cancellationToken);
|
|
return;
|
|
}
|
|
|
|
var text = "📅 <b>Ближайшие игры:</b>\n\n";
|
|
foreach (var s in sessionsList)
|
|
{
|
|
var seats = s.MaxPlayers.HasValue
|
|
? $"{s.PlayerCount}/{s.MaxPlayers.Value}"
|
|
: s.PlayerCount.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
|
var waitlist = s.WaitlistCount > 0 ? $", ожидание: {s.WaitlistCount}" : string.Empty;
|
|
text += $"🔹 <b>{s.ScheduledAt.FormatMoscow()}</b> — {System.Net.WebUtility.HtmlEncode(s.Title)} (Места: {seats}{waitlist})\n";
|
|
}
|
|
|
|
var isGm = message.From?.Id == sessionsList.First().GmId;
|
|
var keyboard = isGm
|
|
? new Telegram.Bot.Types.ReplyMarkups.InlineKeyboardMarkup(
|
|
sessionsList.Select(s => new[] { Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton.WithCallbackData($"🗑 Удалить {s.ScheduledAt.FormatMoscowShort()}", $"delete_session:{s.Id}") }))
|
|
: null;
|
|
|
|
await botClient.SendMessage(
|
|
chatId: message.Chat.Id,
|
|
text: text,
|
|
parseMode: Telegram.Bot.Types.Enums.ParseMode.Html,
|
|
replyMarkup: keyboard,
|
|
cancellationToken: cancellationToken);
|
|
}
|
|
}
|