using Insight.TelegramBot; using Insight.TelegramBot.Models; using Microsoft.Extensions.Logging; using Nocr.TelegramClient.AppServices.TextSubscriptions; using Nocr.TelegramClient.AppServices.Users; using Telegram.Bot.Exceptions; using Telegram.Bot.Types; namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; public sealed class MessageDispatcherHandler : IMessageDispatcherHandler { private readonly ILogger _logger; private readonly IBot _bot; private readonly IMessageDispatcherQueue _queue; private readonly IUsersService _usersService; private readonly ITextMatcherService _textMatcherService; public MessageDispatcherHandler(ILogger logger, IBot bot, IMessageDispatcherQueue queue, IUsersService usersService, ITextMatcherService textMatcherService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _bot = bot ?? throw new ArgumentNullException(nameof(bot)); _queue = queue ?? throw new ArgumentNullException(nameof(queue)); _usersService = usersService ?? throw new ArgumentNullException(nameof(usersService)); _textMatcherService = textMatcherService ?? throw new ArgumentNullException(nameof(textMatcherService)); } public async Task Handle(CancellationToken cancellationToken = default) { if (_queue.TryDequeue(out var message)) { switch (message) { case TextMessage tm: try { await _bot.SendMessageAsync(tm, cancellationToken); } catch (ApiRequestException ex) when (ex.ErrorCode == 403) { _logger.LogWarning("Bot can't interract with user {ChatId}.", tm.ChatId); _logger.LogDebug(ex.ToString()); try { var user = await _usersService.GetByIdentity(tm.ChatId.Identifier ?? 0, cancellationToken); if (user != null) { await _usersService.BlockBot(user.Id, cancellationToken); await _textMatcherService.DeactivateAllUserSubscriptions(user.Id, cancellationToken); _logger.LogInformation("Successfully deactivated user {UserId} subscriptions. ", tm.ChatId); } else { _logger.LogWarning("Could not find user with TelegramId {ChatId} to mark as blocked.", tm.ChatId); } } catch (Exception blockEx) { _logger.LogError(blockEx, "Failed to process user blocking for TelegramId {ChatId}.", tm.ChatId); } } break; case AnimationMessage am: await _bot.SendAnimationAsync(am, cancellationToken); break; default: _logger.LogWarning("Dequeued message has unsupported type: {Type}.", typeof(Message).FullName); break; } } } }