Files
TeleWave/backend/src/TeleWave.Application/Notifications/Subscribers/ListTelegramSubscribersQueryHandler.cs
T
Leonid Pershin 2b03e43a83
ci / build-backend (push) Successful in 2m38s
ci / build-frontend (push) Successful in 1m16s
ci / tests (push) Successful in 2m33s
ci / sonar (push) Successful in 3m48s
Add Telegram bot integration and related features
Implemented Telegram bot functionality, including settings management, subscriber tracking, and link generation for user interaction. Updated the backend to support new Telegram-related services and database entities. Enhanced the frontend to display Telegram options and allow users to open a chat with the bot. Localization strings were added for both English and Russian to support the new features. This integration aims to improve user engagement through Telegram notifications and interactions.
2026-07-31 07:58:18 +03:00

64 lines
2.7 KiB
C#

using LiteCqrs;
using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;
namespace TeleWave.Application.Notifications.Subscribers;
/// <summary>
/// Кто подписан и на что. Нужен не ради красоты: рассылка уходит в чужие чаты, и админ должен
/// видеть список — иначе «бот кому-то что-то шлёт» проверяется только по логам Telegram.
/// </summary>
public sealed class ListTelegramSubscribersQueryHandler(
IAppDbContext dbContext,
IIdentityService identity
) : IQueryHandler<ListTelegramSubscribersQuery, Result<IReadOnlyList<TelegramSubscriberDto>>>
{
public async Task<Result<IReadOnlyList<TelegramSubscriberDto>>> Handle(
ListTelegramSubscribersQuery query,
CancellationToken cancellationToken
)
{
var subscribers = await dbContext
.TelegramSubscribers.AsNoTracking()
.Include(s => s.Subscriptions)
.OrderByDescending(s => s.LastSeenAt ?? s.CreatedAt)
.ToListAsync(cancellationToken);
var channelNames = await dbContext
.Channels.AsNoTracking()
.ToDictionaryAsync(c => c.Id, c => c.Name, cancellationToken);
// Имена пользователей — через порт: Identity живёт в инфраструктуре, и таблицы его
// прикладной слой не видит.
var userNames = new Dictionary<Guid, string>();
foreach (var userId in subscribers.Select(s => s.UserId).Distinct())
{
if (await identity.GetProfileAsync(userId, cancellationToken) is { } profile)
userNames[userId] = profile.UserName;
}
var result = subscribers
.Select(s => new TelegramSubscriberDto(
s.Id,
s.ChatId,
s.DisplayName,
userNames.GetValueOrDefault(s.UserId),
s.IsStopped,
s.CreatedAt,
s.LastSeenAt,
s.Subscriptions.GroupBy(x => x.ChannelId)
.Select(g => new TelegramSubscriptionDto(
g.Key,
// Канал могли удалить — подписки на него остаются висеть, и это надо видеть.
channelNames.GetValueOrDefault(g.Key) ?? "—",
g.Select(x => x.Kind.ToString()).OrderBy(x => x).ToList()
))
.ToList()
))
.ToList();
return Result.Success<IReadOnlyList<TelegramSubscriberDto>>(result);
}
}