From c45e22131d073d66f6dc5757dbbd196d0872d18e Mon Sep 17 00:00:00 2001 From: Ruberoid Date: Mon, 21 Jul 2025 17:13:18 +0300 Subject: [PATCH] Added autodisable subscriptions if user blocked bot! --- Directory.Packages.props | 6 +-- .../MessageDispatcherHandler.cs | 31 ++++++++++++- .../ServiceCollectionExtensions.cs | 2 + .../TextSubscriptions/ITextMatcherService.cs | 19 ++++++++ .../TextSubscriptions/TextMatcherService.cs | 45 +++++++++++++++++++ .../Users/IUsersService.cs | 2 + .../Users/UsersService.cs | 5 +++ 7 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/Nocr.TelegramClient.AppServices/TextSubscriptions/ITextMatcherService.cs create mode 100644 src/Nocr.TelegramClient.AppServices/TextSubscriptions/TextMatcherService.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 8a90382..9f90e99 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,9 +11,9 @@ - - - + + + diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs index 1cdcf5c..258c088 100644 --- a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs @@ -1,6 +1,8 @@ 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; @@ -11,12 +13,16 @@ 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) + 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) @@ -34,7 +40,28 @@ public sealed class MessageDispatcherHandler : IMessageDispatcherHandler ex.Message.Equals("Forbidden: bot was blocked by the user", StringComparison.OrdinalIgnoreCase)) { - _logger.LogWarning(ex, "Failed to deliver message due bot was blocked by the user [{ChatId}]", tm.ChatId); + _logger.LogWarning("Bot was blocked by user {ChatId}, marking user as blocked", tm.ChatId); + + 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 blocked user {UserId} (ChatId: {ChatId}) and deactivated all subscriptions", user.Id, tm.ChatId); + } + else + { + _logger.LogWarning("Could not find user with ChatId {ChatId} to mark as blocked", tm.ChatId); + } + } + catch (Exception blockEx) + { + _logger.LogError(blockEx, "Failed to process user blocking for ChatId {ChatId}", tm.ChatId); + } } break; case AnimationMessage am: diff --git a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs index 7cb455c..df353a1 100644 --- a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs +++ b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Options; using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Nocr.TelegramClient.AppServices.Handlers; using Nocr.TelegramClient.AppServices.Options; +using Nocr.TelegramClient.AppServices.TextSubscriptions; using Nocr.TelegramClient.AppServices.TextSubscriptions.Handlers; using Nocr.TelegramClient.AppServices.Users; using Nocr.TextMatcher.Api.Contracts.TextMatches; @@ -50,6 +51,7 @@ public static class ServiceCollectionExtensions }); services.AddScoped(); + services.AddScoped(); services.Configure(configuration.GetSection(nameof(MessageDispatcherOptions))); services.AddSingleton(); diff --git a/src/Nocr.TelegramClient.AppServices/TextSubscriptions/ITextMatcherService.cs b/src/Nocr.TelegramClient.AppServices/TextSubscriptions/ITextMatcherService.cs new file mode 100644 index 0000000..1c5e3a1 --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/TextSubscriptions/ITextMatcherService.cs @@ -0,0 +1,19 @@ +using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto; +using Nocr.TextMatcher.Api.Contracts.TextMatches.Requests; + +namespace Nocr.TelegramClient.AppServices.TextSubscriptions; + +public interface ITextMatcherService +{ + Task CreateSubscription(CreateTextSubscriptionRequest request, CancellationToken cancellationToken = default); + + Task GetUserSubscriptions(long userId, CancellationToken cancellationToken = default); + + Task ActivateSubscription(long subscriptionId, CancellationToken cancellationToken = default); + + Task DisableSubscription(long subscriptionId, CancellationToken cancellationToken = default); + + Task DeleteSubscription(long subscriptionId, CancellationToken cancellationToken = default); + + Task DeactivateAllUserSubscriptions(long userId, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/TextSubscriptions/TextMatcherService.cs b/src/Nocr.TelegramClient.AppServices/TextSubscriptions/TextMatcherService.cs new file mode 100644 index 0000000..47f00ed --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/TextSubscriptions/TextMatcherService.cs @@ -0,0 +1,45 @@ +using Nocr.TextMatcher.Api.Contracts.TextMatches; +using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto; +using Nocr.TextMatcher.Api.Contracts.TextMatches.Requests; + +namespace Nocr.TelegramClient.AppServices.TextSubscriptions; + +public sealed class TextMatcherService : ITextMatcherService +{ + private readonly ITextSubscriptionsController _textSubscriptionsController; + + public TextMatcherService(ITextSubscriptionsController textSubscriptionsController) + { + _textSubscriptionsController = textSubscriptionsController ?? throw new ArgumentNullException(nameof(textSubscriptionsController)); + } + + public Task CreateSubscription(CreateTextSubscriptionRequest request, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.Create(request, cancellationToken); + } + + public Task GetUserSubscriptions(long userId, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.GetByUserId(userId, cancellationToken); + } + + public Task ActivateSubscription(long subscriptionId, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.Activate(subscriptionId, cancellationToken); + } + + public Task DisableSubscription(long subscriptionId, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.Disable(subscriptionId, cancellationToken); + } + + public Task DeleteSubscription(long subscriptionId, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.Delete(subscriptionId, cancellationToken); + } + + public Task DeactivateAllUserSubscriptions(long userId, CancellationToken cancellationToken = default) + { + return _textSubscriptionsController.DeactivateAllSubscriptionsById(userId, cancellationToken); + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Users/IUsersService.cs b/src/Nocr.TelegramClient.AppServices/Users/IUsersService.cs index f96089d..ce1b7d6 100644 --- a/src/Nocr.TelegramClient.AppServices/Users/IUsersService.cs +++ b/src/Nocr.TelegramClient.AppServices/Users/IUsersService.cs @@ -9,4 +9,6 @@ public interface IUsersService public Task GetByIdentity(long telegramId, CancellationToken cancellationToken = default); public Task GetById(long id, CancellationToken cancellationToken = default); + + public Task BlockBot(long userId, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Users/UsersService.cs b/src/Nocr.TelegramClient.AppServices/Users/UsersService.cs index aa7c942..ac583f0 100644 --- a/src/Nocr.TelegramClient.AppServices/Users/UsersService.cs +++ b/src/Nocr.TelegramClient.AppServices/Users/UsersService.cs @@ -44,4 +44,9 @@ public sealed class UsersService : IUsersService { return _usersController.GetById(id, cancellationToken); } + + public Task BlockBot(long userId, CancellationToken cancellationToken = default) + { + return _usersController.BlockBot(userId, cancellationToken); + } } \ No newline at end of file