nazarovsa/subscription_type (#12)

Reviewed-on: #12
Co-authored-by: Sergey Nazarov <insight.appdev@gmail.com>
Co-committed-by: Sergey Nazarov <insight.appdev@gmail.com>
This commit is contained in:
Sergey Nazarov 2024-05-18 12:49:00 +00:00 committed by nazarovsa
parent a69d372362
commit ea5cb89121
14 changed files with 168 additions and 44 deletions

View File

@ -17,8 +17,6 @@ public sealed class AddSubscriptionHandler : IMatchingUpdateHandler<AddSubscript
private readonly IBot _bot; private readonly IBot _bot;
private readonly IMessageDispatcherQueue _messageDispatcherQueue; private readonly IMessageDispatcherQueue _messageDispatcherQueue;
private const string FaqFileId = "CgACAgIAAxkBAAIPQmY5H7c3pi5_4OxdPbpRVdnwEFMxAAIBTAACnxzJSefFRShccLRXNQQ";
public AddSubscriptionHandler(ILogger<AddSubscriptionHandler> logger, ILocalizer localizer, IBot bot, IMessageDispatcherQueue messageDispatcherQueue) public AddSubscriptionHandler(ILogger<AddSubscriptionHandler> logger, ILocalizer localizer, IBot bot, IMessageDispatcherQueue messageDispatcherQueue)
{ {
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
@ -32,10 +30,9 @@ public sealed class AddSubscriptionHandler : IMatchingUpdateHandler<AddSubscript
var chatId = update.CallbackQuery.Message.Chat.Id; var chatId = update.CallbackQuery.Message.Chat.Id;
var messageId = update.CallbackQuery.Message.MessageId; var messageId = update.CallbackQuery.Message.MessageId;
var message = new AnimationMessage(chatId) var message = new TextMessage(chatId)
{ {
InputOnlineFile = new InputFileId(FaqFileId), Text = _localizer.Get(nameof(AddSubscriptionHandler), "Text"),
Caption = _localizer.Get(nameof(AddSubscriptionHandler), "Text"),
ReplyMarkup = new InlineKeyboardMarkup(new InlineKeyboardButton(_localizer.Get("buttons", "back")) ReplyMarkup = new InlineKeyboardMarkup(new InlineKeyboardButton(_localizer.Get("buttons", "back"))
{ {
CallbackData = NocrCallbackData.Start().ToString() CallbackData = NocrCallbackData.Start().ToString()

View File

@ -0,0 +1,40 @@
using System.Text.RegularExpressions;
using Insight.Localizer;
using Insight.TelegramBot;
using Insight.TelegramBot.Handling.Handlers;
using Microsoft.Extensions.Logging;
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
using Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeExactMessage;
using Nocr.TelegramClient.AppServices.Users;
using Nocr.TextMatcher.Api.Contracts.TextMatches;
using Nocr.TextMatcher.Contracts;
using Telegram.Bot.Types;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeAllMessage;
public sealed class SubscribeAllMessageHandler : SubscribeHandlerBase, IMatchingUpdateHandler<SubscribeAllMessageMatcher>
{
/// <summary>
/// Regex to match command "/subscribe_all @username keywords". <br/>
/// For instance, "/subscribe_all @baraholka обувь ботинки сапоги" will create match for a current user with type "All" and pattern "обувь ботинки сапоги".
/// </summary>
private static Regex _commandRegex =
new Regex(@"^/subscribe_all (.*\B@(?=\w{5,32}\b)[a-zA-Z0-9]+(?:_[а-яА-Яa-zA-Z0-9]+)*) (\s*[а-яА-ЯA-Za-z0-9]+(?:\s+[а-яА-ЯA-Za-z0-9]+)*\s*)$",
RegexOptions.Compiled);
public SubscribeAllMessageHandler(
ILogger<SubscribeAllMessageHandler> logger,
ILocalizer localizer,
IMessageDispatcherQueue messageQueue,
IUsersService usersService,
IBot bot,
ITextSubscriptionsController subscriptionsController)
: base(logger, localizer, messageQueue, bot, usersService, subscriptionsController)
{
}
public Task Handle(Update update, CancellationToken cancellationToken = default)
{
return base.Handle(update, _commandRegex, TextSubscriptionRule.AllWords, cancellationToken);
}
}

View File

@ -0,0 +1,11 @@
using Insight.TelegramBot.Handling.Matchers.TextMatchers;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeAllMessage;
public sealed class SubscribeAllMessageMatcher : TextStartWithUpdateMatcher
{
public SubscribeAllMessageMatcher()
{
Template = "/subscribe_all ";
}
}

View File

@ -0,0 +1,42 @@
using System.Text.RegularExpressions;
using Insight.Localizer;
using Insight.TelegramBot;
using Insight.TelegramBot.Handling.Handlers;
using Microsoft.Extensions.Logging;
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
using Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeExactMessage;
using Nocr.TelegramClient.AppServices.Users;
using Nocr.TextMatcher.Api.Contracts.TextMatches;
using Nocr.TextMatcher.Contracts;
using Telegram.Bot.Types;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeAnyMessage;
public sealed class SubscribeAnyMessageHandler : SubscribeHandlerBase,
IMatchingUpdateHandler<SubscribeAnyMessageMatcher>
{
/// <summary>
/// Regex to match command "/subscribe_any @username keywords". <br/>
/// For instance, "/subscribe_any @baraholka обувь ботинки сапоги" will create match for a current user with type "Any" and pattern "обувь ботинки сапоги".
/// </summary>
private static Regex _commandRegex =
new Regex(
@"^/subscribe_any (.*\B@(?=\w{5,32}\b)[a-zA-Z0-9]+(?:_[а-яА-Яa-zA-Z0-9]+)*) (\s*[а-яА-ЯA-Za-z0-9]+(?:\s+[а-яА-ЯA-Za-z0-9]+)*\s*)$",
RegexOptions.Compiled);
public SubscribeAnyMessageHandler(
ILogger<SubscribeAnyMessageHandler> logger,
ILocalizer localizer,
IMessageDispatcherQueue messageQueue,
IUsersService usersService,
IBot bot,
ITextSubscriptionsController subscriptionsController)
: base(logger, localizer, messageQueue, bot, usersService, subscriptionsController)
{
}
public Task Handle(Update update, CancellationToken cancellationToken = default)
{
return base.Handle(update, _commandRegex, TextSubscriptionRule.AnyWord, cancellationToken);
}
}

View File

@ -0,0 +1,11 @@
using Insight.TelegramBot.Handling.Matchers.TextMatchers;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeAnyMessage;
public sealed class SubscribeAnyMessageMatcher : TextStartWithUpdateMatcher
{
public SubscribeAnyMessageMatcher()
{
Template = "/subscribe_any ";
}
}

View File

@ -0,0 +1,39 @@
using System.Text.RegularExpressions;
using Insight.Localizer;
using Insight.TelegramBot;
using Insight.TelegramBot.Handling.Handlers;
using Microsoft.Extensions.Logging;
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
using Nocr.TelegramClient.AppServices.Users;
using Nocr.TextMatcher.Api.Contracts.TextMatches;
using Nocr.TextMatcher.Contracts;
using Telegram.Bot.Types;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeExactMessage;
public class SubscribeExactMessageHandler : SubscribeHandlerBase, IMatchingUpdateHandler<SubscribeExactMessageMatcher>
{
/// <summary>
/// Regex to match command "/subscribe @username keywords". <br/>
/// For instance, "/subscribe @baraholka обувь" will create match for a current user with type "Full" and pattern "обувь".
/// </summary>
private static Regex _commandRegex =
new Regex(@"^/subscribe (.*\B@(?=\w{5,32}\b)[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*.*) ([а-яА-Яa-zA-Z0-9]{3,})$",
RegexOptions.Compiled);
public SubscribeExactMessageHandler(
ILogger<SubscribeExactMessageHandler> logger,
ILocalizer localizer,
IMessageDispatcherQueue messageQueue,
IUsersService usersService,
IBot bot,
ITextSubscriptionsController subscriptionsController)
: base(logger, localizer, messageQueue, bot, usersService, subscriptionsController)
{
}
public Task Handle(Update update, CancellationToken cancellationToken = default)
{
return base.Handle(update, _commandRegex, TextSubscriptionRule.Full, cancellationToken);
}
}

View File

@ -0,0 +1,11 @@
using Insight.TelegramBot.Handling.Matchers.TextMatchers;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeExactMessage;
public sealed class SubscribeExactMessageMatcher : TextStartWithUpdateMatcher
{
public SubscribeExactMessageMatcher()
{
Template = "/subscribe ";
}
}

View File

@ -2,7 +2,6 @@ using System.Text.RegularExpressions;
using FormatWith; using FormatWith;
using Insight.Localizer; using Insight.Localizer;
using Insight.TelegramBot; using Insight.TelegramBot;
using Insight.TelegramBot.Handling.Handlers;
using Insight.TelegramBot.Models; using Insight.TelegramBot.Models;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
@ -13,47 +12,32 @@ using Nocr.TextMatcher.Api.Contracts.TextMatches.Requests;
using Nocr.TextMatcher.Contracts; using Nocr.TextMatcher.Contracts;
using Telegram.Bot.Types; using Telegram.Bot.Types;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeMessage; namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeExactMessage;
public class SubscribeMessageHandler : ViewSubscriptionHandlerBase, IMatchingUpdateHandler<SubscribeMessageMatcher> public abstract class SubscribeHandlerBase : ViewSubscriptionHandlerBase
{ {
/// <summary> protected SubscribeHandlerBase(ILogger logger, ILocalizer localizer, IMessageDispatcherQueue messageQueue, IBot bot,
/// Regex to match command "/subscribe @username match_type keywords". <br/> IUsersService usersService, ITextSubscriptionsController subscriptionsController)
/// For instance, "/subscribe @baraholka 1 обувь ботинки сапоги" will create match for a current user with type "All" and pattern "обувь ботинки сапоги".
/// </summary>
private static Regex _commandRegex =
new Regex(@"^/subscribe (.*\B@(?=\w{5,32}\b)[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*.*) (.{3,})$",
RegexOptions.Compiled);
public SubscribeMessageHandler(
ILogger<SubscribeMessageHandler> logger,
ILocalizer localizer,
IMessageDispatcherQueue messageQueue,
IUsersService usersService,
IBot bot,
ITextSubscriptionsController subscriptionsController)
: base(logger, localizer, messageQueue, bot, usersService, subscriptionsController) : base(logger, localizer, messageQueue, bot, usersService, subscriptionsController)
{ {
} }
public async Task Handle(Update update, CancellationToken cancellationToken = default) protected async Task Handle(Update update, Regex regex, TextSubscriptionRule rule, CancellationToken cancellationToken = default)
{ {
var receiverId = update.Message.Chat.Id; var receiverId = update.Message.Chat.Id;
var match = _commandRegex.Match(update.Message.Text); var match = regex.Match(update.Message.Text);
if (!match.Success) if (!match.Success)
{ {
MessageQueue.Enqueue(new TextMessage(receiverId) MessageQueue.Enqueue(new TextMessage(receiverId)
{ {
Text = Localizer.Get(nameof(SubscribeMessageHandler), "CommandHasWrongFormat") Text = Localizer.Get(nameof(SubscribeHandlerBase), "CommandHasWrongFormat")
}); });
return; return;
} }
var username = match.Groups[1].Value.TrimStart('@'); var username = match.Groups[1].Value.TrimStart('@');
var template = match.Groups[2].Value; var template = match.Groups[2].Value;
// note(nazarovsa): Temporary for simplify usage
var rule = TextSubscriptionRule.Full;
var user = await UsersService.GetOrCreate(receiverId, update.Message.From.Username, cancellationToken); var user = await UsersService.GetOrCreate(receiverId, update.Message.From.Username, cancellationToken);
var subscriptionId = await SubscriptionsController.Create(new CreateTextSubscriptionRequest var subscriptionId = await SubscriptionsController.Create(new CreateTextSubscriptionRequest
@ -66,7 +50,7 @@ public class SubscribeMessageHandler : ViewSubscriptionHandlerBase, IMatchingUpd
MessageQueue.Enqueue(new TextMessage(receiverId) MessageQueue.Enqueue(new TextMessage(receiverId)
{ {
Text = Localizer.Get(nameof(SubscribeMessageHandler), "Text") Text = Localizer.Get(nameof(SubscribeHandlerBase), "Text")
.FormatWith(new { Id = subscriptionId }) .FormatWith(new { Id = subscriptionId })
}); });

View File

@ -1,11 +0,0 @@
using Insight.TelegramBot.Handling.Matchers.TextMatchers;
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeMessage;
public sealed class SubscribeMessageMatcher : TextStartWithUpdateMatcher
{
public SubscribeMessageMatcher()
{
Template = "/subscribe";
}
}

View File

@ -1,5 +1,5 @@
{ {
"Full": "Полное", "Full": "Полное совпадение",
"AllWords": "Все слова из списка", "AllWords": "Все слова из списка",
"AnyWord": "Одно слово из списка" "AnyWord": "Одно слово из списка"
} }

View File

@ -1,7 +1,7 @@
{ {
"Active": "Активна", "Active": "Активна",
"Inactive": "Не активна", "Inactive": "Не активна",
"Text": "Подписка <b>#{Id}</b>\nЧат: (@{ChatUsername})\nСтатус: {ActiveText}\nШаблон: <i>{Template}</i>", "Text": "✉️ Подписка <b>#{Id}</b>\n<b>💬 Чат</b>: @{ChatUsername}\n<b>👀 Статус</b>: {ActiveText}\n<b>🎲 Тип подписки</b>: {Rule}\n<b>🔑 Шаблон</b>: <i>{Template}</i>",
"ActivateButton": "Активировать", "ActivateButton": "Активировать",
"DeactivateButton": "Деактивировать" "DeactivateButton": "Деактивировать"
} }

View File

@ -1,3 +1,3 @@
{ {
"Text": "Формат команды для подписки:\n\n`/subscribe @chat_username ключевое_слово`.\n\nКлючевое слово должно быть более 2 символов. \n\nНапример: `/subscribe @baraholka_tbi iphone`." "Text": "Существует несколько вариантов подписки: <b>точное совпадение</b>, <b>одно слово из списка</b>, <b>все слова из списка</b>.\n\nДля подписки с <b>точным совпадением</b> пришлите команду в формате:\n`/subscribe @chat_username ключевое_слово`.\nНапример: `/subscribe @baraholka_tbi iphone` подпишется на все сообщения, в которых содержится ключевое слово <i>iphone</i>.\n\nДля подписки на <b>одно слово из списка</b> пришлите команду в формате:\n`/subscribe_any @chat_username ключевые_словаерез_пробел`\nНапример `/subscribe_any @baraholka_tbi macbook mac макбук` создаст подписку на сообщения, в которых встречается <b>ХОТЯ БЫ ОДНО</b> слово из списка <i>macbook mac макбук</i>\n\nДля подписки на <b>все слова из списка</b> пришлите команду в формате: `/subscribe_all @chat_username ключевые_словаерез_пробел`\nНапример: `/subscribe_any @baraholka_tbi велосипед cube` подпишется на все сообщения, в которых <b>ОДНОВРЕМЕННО</b> содержатся все ключевые слова из списка <i>велосипед cube</i>.\n\nКлючевое слово должно содержать более 2 символов."
} }