nazarovsa/subscription_commands (#6)
Reviewed-on: #6 Co-authored-by: Sergey Nazarov <insight.appdev@gmail.com> Co-committed-by: Sergey Nazarov <insight.appdev@gmail.com>
This commit is contained in:
parent
43dbf5b724
commit
5e99e802ec
27
src/Nocr.TelegramClient.AppServices/Bots/IBotExtensions.cs
Normal file
27
src/Nocr.TelegramClient.AppServices/Bots/IBotExtensions.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
public static class BotExtensions
|
||||
{
|
||||
public static async Task EditOrSendTextMessage(this IBot bot,
|
||||
int messageId,
|
||||
TextMessage message,
|
||||
ILogger? logger = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await bot.EditMessageTextAsync(messageId, message, cancellationToken);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger?.LogWarning(ex, "Не удалось отредактировать текстовое сообщение");
|
||||
}
|
||||
|
||||
await bot.SendMessageAsync(message, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
30
src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs
Normal file
30
src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Insight.TelegramBot;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
public class NocrCallbackData : CallbackData<NocrState>
|
||||
{
|
||||
public NocrCallbackData(NocrState nextState, params string[] args) : base(nextState, args)
|
||||
{
|
||||
}
|
||||
|
||||
public static NocrCallbackData ActivateSubscription(long subscriptionId)
|
||||
{
|
||||
return new NocrCallbackData(NocrState.ActivateSubscription, subscriptionId.ToString());
|
||||
}
|
||||
|
||||
public static NocrCallbackData DeactivateSubscription(long subscriptionId)
|
||||
{
|
||||
return new NocrCallbackData(NocrState.DeactivateSubscription, subscriptionId.ToString());
|
||||
}
|
||||
|
||||
public static NocrCallbackData DeleteSubscription(long subscriptionId)
|
||||
{
|
||||
return new NocrCallbackData(NocrState.DeleteSubscription, subscriptionId.ToString());
|
||||
}
|
||||
|
||||
public static NocrCallbackData ViewSubscription(long subscriptionId)
|
||||
{
|
||||
return new NocrCallbackData(NocrState.ViewSubscription, subscriptionId.ToString());
|
||||
}
|
||||
}
|
||||
12
src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs
Normal file
12
src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
public enum NocrState
|
||||
{
|
||||
// Commands
|
||||
ActivateSubscription = 1,
|
||||
DeactivateSubscription = 2,
|
||||
DeleteSubscription = 3,
|
||||
|
||||
// States
|
||||
ViewSubscription = 4
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
using FormatWith;
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Keyboards;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Matches;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
|
||||
public abstract class ViewSubscriptionHandlerBase
|
||||
{
|
||||
protected ILogger Logger { get; }
|
||||
protected IBot Bot { get; }
|
||||
protected ITextSubscriptionsController SubscriptionsController { get; }
|
||||
protected ILocalizer Localizer { get; }
|
||||
protected IMessageDispatcherQueue MessageQueue { get; }
|
||||
|
||||
protected ViewSubscriptionHandlerBase(ILogger logger, ILocalizer localizer, IMessageDispatcherQueue messageQueue,
|
||||
IBot bot, ITextSubscriptionsController subscriptionsController)
|
||||
{
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
Bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
||||
SubscriptionsController =
|
||||
subscriptionsController ?? throw new ArgumentNullException(nameof(subscriptionsController));
|
||||
Localizer = localizer ?? throw new ArgumentNullException(nameof(localizer));
|
||||
MessageQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue));
|
||||
}
|
||||
|
||||
public async Task SendSubscriptionMessage(long receiverId, TextSubscriptionData subscription,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var message = await GetMessage(receiverId, subscription, cancellationToken);
|
||||
MessageQueue.Enqueue(message);
|
||||
}
|
||||
|
||||
public async Task EditSubscriptionMessage(long receiverId, int messageId, long subscriptionId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var subscription = await SubscriptionsController.GetById(subscriptionId, cancellationToken);
|
||||
var message = await GetMessage(receiverId, subscription, cancellationToken);
|
||||
await Bot.EditOrSendTextMessage(messageId, message, Logger, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<TextMessage> GetMessage(long receiverId, TextSubscriptionData subscription,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var subscriptions = await SubscriptionsController.GetByUserId(subscription.UserId, cancellationToken);
|
||||
var ordered = subscriptions.OrderBy(x => x.Id).ToList();
|
||||
var indexOf = ordered.FindIndex(x => x.Id == subscription.Id);
|
||||
long? prevId = indexOf > 0 ? ordered[indexOf - 1].Id : null;
|
||||
long? nextId = indexOf < ordered.Count - 1 ? ordered[indexOf + 1].Id : null;
|
||||
|
||||
var textMessage = new TextMessage(receiverId)
|
||||
{
|
||||
Text = GetText(subscription),
|
||||
ParseMode = ParseMode.Html,
|
||||
ReplyMarkup = BuildKeyBoard(subscription, prevId, nextId).InlineKeyboardMarkup
|
||||
};
|
||||
|
||||
return textMessage;
|
||||
}
|
||||
|
||||
private string GetText(TextSubscriptionData subscription)
|
||||
{
|
||||
var activeText = subscription.Active
|
||||
? Localizer.Get(nameof(ViewSubscriptionHandlerBase), "Active")
|
||||
: Localizer.Get(nameof(ViewSubscriptionHandlerBase), "Inactive");
|
||||
|
||||
var text = Localizer.Get(nameof(ViewSubscriptionHandlerBase), "Text")
|
||||
.FormatWith(new
|
||||
{
|
||||
subscription.Id,
|
||||
subscription.ChatUsername,
|
||||
ActiveText = activeText,
|
||||
Rule = subscription.Rule.TextView(Localizer),
|
||||
subscription.Template
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private VerticalKeyboardMarkup BuildKeyBoard(TextSubscriptionData textSubscription, long? prevId, long? nextId)
|
||||
{
|
||||
var activeButtonText = textSubscription.Active
|
||||
? Localizer.Get(nameof(ViewSubscriptionHandlerBase), "DeactivateButton")
|
||||
: Localizer.Get(nameof(ViewSubscriptionHandlerBase), "ActivateButton");
|
||||
|
||||
var deleteButtonText = Localizer.Get("Buttons", "Delete");
|
||||
|
||||
var markup = new VerticalKeyboardMarkup();
|
||||
|
||||
var row = new List<InlineKeyboardButton>(2);
|
||||
if (prevId.HasValue)
|
||||
{
|
||||
row.Add(new InlineKeyboardButton(Localizer.Get("Buttons", "PreviousPage"))
|
||||
{
|
||||
CallbackData = NocrCallbackData.ViewSubscription(prevId.Value).ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (nextId.HasValue)
|
||||
{
|
||||
row.Add(new InlineKeyboardButton(Localizer.Get("Buttons", "NextPage"))
|
||||
{
|
||||
CallbackData = NocrCallbackData.ViewSubscription(nextId.Value).ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (row.Count != 0)
|
||||
markup.AddRow(row);
|
||||
|
||||
markup.Add(new InlineKeyboardButton(activeButtonText)
|
||||
{
|
||||
CallbackData = textSubscription.Active
|
||||
? NocrCallbackData.DeactivateSubscription(textSubscription.Id).ToString()
|
||||
: NocrCallbackData.ActivateSubscription(textSubscription.Id).ToString()
|
||||
});
|
||||
|
||||
markup.Add(new InlineKeyboardButton(deleteButtonText)
|
||||
{ CallbackData = NocrCallbackData.DeleteSubscription(textSubscription.Id).ToString() });
|
||||
|
||||
|
||||
return markup;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Telegram.Bot.Types;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.ActivateSubscription;
|
||||
|
||||
public class ActivateSubscriptionHandler : ViewSubscriptionHandlerBase, IMatchingUpdateHandler<ActivateSubscriptionMatcher>
|
||||
{
|
||||
public ActivateSubscriptionHandler(ILogger<ActivateSubscriptionHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController)
|
||||
: base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var callbackData = NocrCallbackData.Parse(update.CallbackQuery.Data);
|
||||
var from = update.CallbackQuery.From.Id;
|
||||
|
||||
if (callbackData.Args.Count != 1 || !long.TryParse(callbackData.Args.First(), out var subscriptionId))
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Не удалось извлечь идентификатор подписки. CallbackData: {@CallbackData}, ChatId: {ChatId}, MessageId {MessageId}",
|
||||
callbackData, from, update.CallbackQuery.Message.Chat.Id);
|
||||
SendErrorMessage(from);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await SubscriptionsController.Activate(subscriptionId, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Не удалось деактивировать подписку");
|
||||
SendErrorMessage(from);
|
||||
throw;
|
||||
}
|
||||
|
||||
await EditSubscriptionMessage(from, update.CallbackQuery.Message.MessageId, subscriptionId,
|
||||
CancellationToken.None);
|
||||
}
|
||||
|
||||
private void SendErrorMessage(long from)
|
||||
{
|
||||
MessageQueue.Enqueue(new TextMessage(from)
|
||||
{
|
||||
Text = Localizer.Get(nameof(ActivateSubscriptionHandler), "FailedToActivateSubscription")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using Insight.TelegramBot.Handling.Matchers.CallbackQueryMatchers;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.ActivateSubscription;
|
||||
|
||||
public sealed class ActivateSubscriptionMatcher : StateCallbackQueryMatcher<NocrState>
|
||||
{
|
||||
public ActivateSubscriptionMatcher()
|
||||
{
|
||||
ExpectingState = NocrState.ActivateSubscription;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Telegram.Bot.Types;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.DeactivateSubscription;
|
||||
|
||||
public class DeactivateSubscriptionHandler : ViewSubscriptionHandlerBase,
|
||||
IMatchingUpdateHandler<DeactivateSubscriptionMatcher>
|
||||
{
|
||||
|
||||
public DeactivateSubscriptionHandler(ILogger<DeactivateSubscriptionHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController)
|
||||
: base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var callbackData = NocrCallbackData.Parse(update.CallbackQuery.Data);
|
||||
var from = update.CallbackQuery.From.Id;
|
||||
|
||||
if (callbackData.Args.Count != 1 || !long.TryParse(callbackData.Args.First(), out var subscriptionId))
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Не удалось извлечь идентификатор подписки. CallbackData: {@CallbackData}, ChatId: {ChatId}, MessageId {MessageId}",
|
||||
callbackData, from, update.CallbackQuery.Message.Chat.Id);
|
||||
SendErrorMessage(from);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await SubscriptionsController.Disable(subscriptionId, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Не удалось деактивировать подписку");
|
||||
SendErrorMessage(from);
|
||||
throw;
|
||||
}
|
||||
|
||||
await EditSubscriptionMessage(from, update.CallbackQuery.Message.MessageId, subscriptionId, CancellationToken.None);
|
||||
}
|
||||
|
||||
private void SendErrorMessage(long from)
|
||||
{
|
||||
MessageQueue.Enqueue(new TextMessage(from)
|
||||
{
|
||||
Text = Localizer.Get(nameof(DeactivateSubscriptionHandler), "FailedToDeactivateSubscription")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using Insight.TelegramBot.Handling.Matchers.CallbackQueryMatchers;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.DeactivateSubscription;
|
||||
|
||||
public sealed class DeactivateSubscriptionMatcher : StateCallbackQueryMatcher<NocrState>
|
||||
{
|
||||
public DeactivateSubscriptionMatcher()
|
||||
{
|
||||
ExpectingState = NocrState.DeactivateSubscription;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
using FormatWith;
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.DeactivateSubscription;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Telegram.Bot.Types;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.DeleteSubscription;
|
||||
|
||||
public class DeleteSubscriptionHandler : ViewSubscriptionHandlerBase,
|
||||
IMatchingUpdateHandler<DeleteSubscriptionMatcher>
|
||||
{
|
||||
public DeleteSubscriptionHandler(ILogger<DeleteSubscriptionHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController)
|
||||
: base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var callbackData = NocrCallbackData.Parse(update.CallbackQuery.Data);
|
||||
var from = update.CallbackQuery.From.Id;
|
||||
|
||||
if (callbackData.Args.Count != 1 || !long.TryParse(callbackData.Args.First(), out var subscriptionId))
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Не удалось извлечь идентификатор подписки. CallbackData: {@CallbackData}, ChatId: {ChatId}, MessageId {MessageId}",
|
||||
callbackData, from, update.CallbackQuery.Message.Chat.Id);
|
||||
SendErrorMessage(from);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await SubscriptionsController.Delete(subscriptionId, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Не удалось удалить подписку");
|
||||
SendErrorMessage(from);
|
||||
throw;
|
||||
}
|
||||
|
||||
var message = new TextMessage(from)
|
||||
{
|
||||
Text = Localizer.Get(nameof(DeleteSubscriptionHandler), "Text")
|
||||
.FormatWith(new { Id = subscriptionId })
|
||||
};
|
||||
|
||||
await Bot.EditOrSendTextMessage(update.CallbackQuery.Message.MessageId, message, Logger, CancellationToken.None);
|
||||
}
|
||||
|
||||
private void SendErrorMessage(long from)
|
||||
{
|
||||
MessageQueue.Enqueue(new TextMessage(from)
|
||||
{
|
||||
Text = Localizer.Get(nameof(DeactivateSubscriptionHandler), "FailedToDeleteSubscription")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using Insight.TelegramBot.Handling.Matchers.CallbackQueryMatchers;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.DeleteSubscription;
|
||||
|
||||
public sealed class DeleteSubscriptionMatcher : StateCallbackQueryMatcher<NocrState>
|
||||
{
|
||||
public DeleteSubscriptionMatcher()
|
||||
{
|
||||
ExpectingState = NocrState.DeleteSubscription;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Telegram.Bot.Types;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.ViewSubscription;
|
||||
|
||||
public class ViewSubscriptionHandler : ViewSubscriptionHandlerBase, IMatchingUpdateHandler<ViewSubscriptionMatcher>
|
||||
{
|
||||
public ViewSubscriptionHandler(ILogger<ViewSubscriptionHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController) :
|
||||
base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var callbackData = NocrCallbackData.Parse(update.CallbackQuery.Data);
|
||||
var from = update.CallbackQuery.From.Id;
|
||||
|
||||
if (callbackData.Args.Count != 1 || !long.TryParse(callbackData.Args.First(), out var subscriptionId))
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Не удалось извлечь идентификатор подписки. CallbackData: {@CallbackData}, ChatId: {ChatId}, MessageId {MessageId}",
|
||||
callbackData, from, update.CallbackQuery.Message.Chat.Id);
|
||||
SendErrorMessage(from);
|
||||
return;
|
||||
}
|
||||
|
||||
await EditSubscriptionMessage(from, update.CallbackQuery.Message.MessageId, subscriptionId, cancellationToken);
|
||||
}
|
||||
|
||||
private void SendErrorMessage(long from)
|
||||
{
|
||||
MessageQueue.Enqueue(new TextMessage(from)
|
||||
{
|
||||
Text = Localizer.Get(nameof(ViewSubscriptionHandler), "FailedToViewSubscription")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using Insight.TelegramBot.Handling.Matchers.CallbackQueryMatchers;
|
||||
using Nocr.TelegramClient.AppServices.Bots;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.ViewSubscription;
|
||||
|
||||
public sealed class ViewSubscriptionMatcher : StateCallbackQueryMatcher<NocrState>
|
||||
{
|
||||
public ViewSubscriptionMatcher()
|
||||
{
|
||||
ExpectingState = NocrState.ViewSubscription;
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@ public class StartMessageHandler : IMatchingUpdateHandler<StartMessageMatcher>
|
||||
var telegramId = update.Message.From.Id;
|
||||
var message = new TextMessage(telegramId)
|
||||
{
|
||||
Text = _localizer.Get("messages", "StartMessage"),
|
||||
Text = _localizer.Get(nameof(StartMessageHandler), "Text"),
|
||||
ParseMode = ParseMode.Html
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using FormatWith;
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TelegramClient.AppServices.Users;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches.Requests;
|
||||
@ -10,11 +15,9 @@ using Telegram.Bot.Types;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeMessage;
|
||||
|
||||
public class SubscribeMessageHandler : IMatchingUpdateHandler<SubscribeMessageMatcher>
|
||||
public class SubscribeMessageHandler : ViewSubscriptionHandlerBase, IMatchingUpdateHandler<SubscribeMessageMatcher>
|
||||
{
|
||||
private readonly IMessageDispatcherQueue _messageQueue;
|
||||
private readonly IUsersService _usersService;
|
||||
private readonly ITextSubscriptionsController _textSubscriptionsController;
|
||||
|
||||
/// <summary>
|
||||
/// Regex to match command "/subscribe @username match_type keywords". <br/>
|
||||
@ -24,26 +27,28 @@ public class SubscribeMessageHandler : IMatchingUpdateHandler<SubscribeMessageMa
|
||||
new Regex(@"/subscribe (.*\B@(?=\w{5,32}\b)[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*.*) (\d{1}) (.*)",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
public SubscribeMessageHandler(IMessageDispatcherQueue messageQueue, IUsersService usersService,
|
||||
ITextSubscriptionsController textSubscriptionsController)
|
||||
public SubscribeMessageHandler(
|
||||
ILogger<SubscribeMessageHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IUsersService usersService,
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController)
|
||||
: base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
_messageQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue));
|
||||
_usersService = usersService ?? throw new ArgumentNullException(nameof(usersService));
|
||||
_textSubscriptionsController =
|
||||
textSubscriptionsController ?? throw new ArgumentNullException(nameof(textSubscriptionsController));
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var telegramId = update.Message.From.Id;
|
||||
var receiverId = update.Message.From.Id;
|
||||
|
||||
var match = _commandRegex.Match(update.Message.Text);
|
||||
if (!match.Success)
|
||||
{
|
||||
_messageQueue.Enqueue(new TextMessage(telegramId)
|
||||
MessageQueue.Enqueue(new TextMessage(receiverId)
|
||||
{
|
||||
// TODO: Add localizer
|
||||
Text = "Команда не удовлетворяет формату"
|
||||
Text = Localizer.Get(nameof(SubscribeMessageHandler), "CommandHasWrongFormat")
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -51,18 +56,17 @@ public class SubscribeMessageHandler : IMatchingUpdateHandler<SubscribeMessageMa
|
||||
var username = match.Groups[1].Value.TrimStart('@');
|
||||
if (!Enum.TryParse<TextSubscriptionRule>(match.Groups[2].Value, true, out var rule))
|
||||
{
|
||||
_messageQueue.Enqueue(new TextMessage(telegramId)
|
||||
MessageQueue.Enqueue(new TextMessage(receiverId)
|
||||
{
|
||||
// TODO: Add localizer
|
||||
Text = "Не удалось извлечь тип подписки"
|
||||
Text = Localizer.Get(nameof(SubscribeMessageHandler), "WrongSubscriptionType")
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var template = match.Groups[3].Value;
|
||||
|
||||
var user = await _usersService.GetOrCreate(telegramId, update.Message.From.Username, cancellationToken);
|
||||
var subscriptionId = await _textSubscriptionsController.Create(new CreateTextSubscriptionRequest
|
||||
var user = await _usersService.GetOrCreate(receiverId, update.Message.From.Username, cancellationToken);
|
||||
var subscriptionId = await SubscriptionsController.Create(new CreateTextSubscriptionRequest
|
||||
{
|
||||
UserId = user.Id,
|
||||
ChatUsername = username,
|
||||
@ -70,10 +74,13 @@ public class SubscribeMessageHandler : IMatchingUpdateHandler<SubscribeMessageMa
|
||||
Template = template,
|
||||
}, cancellationToken);
|
||||
|
||||
_messageQueue.Enqueue(new TextMessage(telegramId)
|
||||
MessageQueue.Enqueue(new TextMessage(receiverId)
|
||||
{
|
||||
// TODO: Add localizer
|
||||
Text = $"Подписка создана: {subscriptionId}"
|
||||
Text = Localizer.Get(nameof(SubscribeMessageHandler), "Text")
|
||||
.FormatWith(new { Id = subscriptionId })
|
||||
});
|
||||
|
||||
var subscription = await SubscriptionsController.GetById(subscriptionId, CancellationToken.None);
|
||||
await SendSubscriptionMessage(receiverId, subscription, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
@ -1,32 +1,30 @@
|
||||
using Insight.Localizer;
|
||||
using Insight.TelegramBot;
|
||||
using Insight.TelegramBot.Handling.Handlers;
|
||||
using Insight.TelegramBot.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Matches;
|
||||
using Nocr.TelegramClient.AppServices.Handlers.BaseHandlers;
|
||||
using Nocr.TelegramClient.AppServices.Users;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscriptionsMessage;
|
||||
|
||||
public class SubscriptionsMessageHandler : IMatchingUpdateHandler<SubscriptionsMessageMatcher>
|
||||
public class SubscriptionsMessageHandler : ViewSubscriptionHandlerBase,
|
||||
IMatchingUpdateHandler<SubscriptionsMessageMatcher>
|
||||
{
|
||||
private readonly ILocalizer _localizer;
|
||||
private readonly IMessageDispatcherQueue _messageQueue;
|
||||
private readonly IUsersService _usersService;
|
||||
private readonly ITextSubscriptionsController _textSubscriptionsController;
|
||||
|
||||
public SubscriptionsMessageHandler(ILocalizer localizer,
|
||||
public SubscriptionsMessageHandler(
|
||||
ILogger<SubscriptionsMessageHandler> logger,
|
||||
ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageQueue,
|
||||
IUsersService usersService,
|
||||
ITextSubscriptionsController textSubscriptionsController)
|
||||
IBot bot,
|
||||
ITextSubscriptionsController subscriptionsController)
|
||||
: base(logger, localizer, messageQueue, bot, subscriptionsController)
|
||||
{
|
||||
_localizer = localizer ?? throw new ArgumentNullException(nameof(localizer));
|
||||
_messageQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue));
|
||||
_usersService = usersService ?? throw new ArgumentNullException(nameof(usersService));
|
||||
_textSubscriptionsController = textSubscriptionsController ??
|
||||
throw new ArgumentNullException(nameof(textSubscriptionsController));
|
||||
}
|
||||
|
||||
public async Task Handle(Update update, CancellationToken cancellationToken = default)
|
||||
@ -34,17 +32,9 @@ public class SubscriptionsMessageHandler : IMatchingUpdateHandler<SubscriptionsM
|
||||
var telegramId = update.Message.From.Id;
|
||||
var user = await _usersService.GetOrCreate(telegramId, update.Message.From.Username, cancellationToken);
|
||||
|
||||
var subscriptions = await _textSubscriptionsController.GetByUserId(user.Id, cancellationToken);
|
||||
var subscriptions = await SubscriptionsController.GetByUserId(user.Id, cancellationToken);
|
||||
var subscription = subscriptions.MinBy(x => x.Id);
|
||||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
var textMessage = new TextMessage(telegramId)
|
||||
{
|
||||
Text = subscription.TextView(_localizer),
|
||||
ParseMode = ParseMode.Html
|
||||
};
|
||||
|
||||
_messageQueue.Enqueue(textMessage);
|
||||
}
|
||||
await SendSubscriptionMessage(telegramId, subscription, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
@ -5,21 +5,20 @@ using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher;
|
||||
using Nocr.TelegramClient.AppServices.Links;
|
||||
using Nocr.TelegramClient.AppServices.Users;
|
||||
using Nocr.TextMatcher.Async.Api.Contracts;
|
||||
using Nocr.Users.Api.Contracts.Users;
|
||||
using Rebus.Handlers;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Matches.Handlers;
|
||||
|
||||
public class TextMatchMatchedHandler : IHandleMessages<TextSubscriptionMatched>
|
||||
public class TextSubscriptionMatched : IHandleMessages<TextMatcher.Async.Api.Contracts.TextSubscriptionMatched>
|
||||
{
|
||||
private readonly ILogger<TextMatchMatchedHandler> _logger;
|
||||
private readonly ILogger<TextSubscriptionMatched> _logger;
|
||||
private readonly ILocalizer _localizer;
|
||||
private readonly IMessageDispatcherQueue _messageDispatcherQueue;
|
||||
private readonly IUsersService _usersService;
|
||||
|
||||
public TextMatchMatchedHandler(ILogger<TextMatchMatchedHandler> logger, ILocalizer localizer,
|
||||
public TextSubscriptionMatched(ILogger<TextSubscriptionMatched> logger, ILocalizer localizer,
|
||||
IMessageDispatcherQueue messageDispatcherQueue, IUsersService usersService)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
@ -29,7 +28,7 @@ public class TextMatchMatchedHandler : IHandleMessages<TextSubscriptionMatched>
|
||||
_usersService = usersService ?? throw new ArgumentNullException(nameof(usersService));
|
||||
}
|
||||
|
||||
public async Task Handle(TextSubscriptionMatched message)
|
||||
public async Task Handle(TextMatcher.Async.Api.Contracts.TextSubscriptionMatched message)
|
||||
{
|
||||
// TODO: Set from user context
|
||||
Localizer.CurrentCulture = "ru-ru";
|
||||
@ -52,7 +51,7 @@ public class TextMatchMatchedHandler : IHandleMessages<TextSubscriptionMatched>
|
||||
|
||||
var link = new PublicTelegramMessageLink(false, message.ChatUsername, message.MessageId);
|
||||
var fromUsername = string.IsNullOrWhiteSpace(message.From) ? "anonymous" : message.From;
|
||||
var text = _localizer.Get("messages", "TextSubscriptionMatched")
|
||||
var text = _localizer.Get(nameof(TextSubscriptionMatched), "Text")
|
||||
.FormatWith(new
|
||||
{
|
||||
SubscriptionRule = message.Rule.TextView(_localizer),
|
||||
@ -1,47 +0,0 @@
|
||||
using FormatWith;
|
||||
using Insight.Localizer;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto;
|
||||
using Nocr.TextMatcher.Contracts;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Matches;
|
||||
|
||||
public static class TextMatchExtensions
|
||||
{
|
||||
public static string TextView(this TextSubscriptionData textSubscription, ILocalizer localizer)
|
||||
{
|
||||
var activeText = textSubscription.Active
|
||||
? localizer.Get(nameof(TextSubscriptionData), "Active")
|
||||
: localizer.Get(nameof(TextSubscriptionData), "Inactive");
|
||||
var activeCommandText = textSubscription.Active
|
||||
? GetFormattedCommand("Deactivate", textSubscription.Id)
|
||||
: GetFormattedCommand("Activate", textSubscription.Id);
|
||||
|
||||
var deleteCommandText = GetFormattedCommand("Delete", textSubscription.Id);
|
||||
return
|
||||
$"[{textSubscription.Id}] (@{textSubscription.ChatUsername}) {activeText}: '{textSubscription.Rule.TextView(localizer)}' > '{textSubscription.Template}'\n{activeCommandText}\n{deleteCommandText}";
|
||||
|
||||
string GetFormattedCommand(string key, long subscriptionId)
|
||||
{
|
||||
return localizer.Get(nameof(TextSubscriptionData), key)
|
||||
.FormatWith(new
|
||||
{
|
||||
SubscriptionId = subscriptionId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static string TextView(this TextSubscriptionRule rule, ILocalizer localizer)
|
||||
{
|
||||
switch (rule)
|
||||
{
|
||||
case TextSubscriptionRule.Full:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.Full));
|
||||
case TextSubscriptionRule.AllWords:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.AllWords));
|
||||
case TextSubscriptionRule.AnyWord:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.AnyWord));
|
||||
default:
|
||||
throw new IndexOutOfRangeException(nameof(rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
using Insight.Localizer;
|
||||
using Nocr.TextMatcher.Contracts;
|
||||
|
||||
namespace Nocr.TelegramClient.AppServices.Matches;
|
||||
|
||||
public static class TextSubscriptionRuleExtensions
|
||||
{
|
||||
public static string TextView(this TextSubscriptionRule rule, ILocalizer localizer)
|
||||
{
|
||||
switch (rule)
|
||||
{
|
||||
case TextSubscriptionRule.Full:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.Full));
|
||||
case TextSubscriptionRule.AllWords:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.AllWords));
|
||||
case TextSubscriptionRule.AnyWord:
|
||||
return localizer.Get(nameof(TextSubscriptionRule), nameof(TextSubscriptionRule.AnyWord));
|
||||
default:
|
||||
throw new IndexOutOfRangeException(nameof(rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,5 +19,4 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nocr.TelegramClient.Core\Nocr.TelegramClient.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -20,7 +20,7 @@ public static class ServiceCollectionExtensions
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
|
||||
// Add registrations here
|
||||
services.AddRebusHandler<TextMatchMatchedHandler>();
|
||||
services.AddRebusHandler<TextSubscriptionMatched>();
|
||||
services.AddHttpClient();
|
||||
|
||||
services.Configure<UsersRestEaseOptions>(configuration.GetSection(nameof(UsersRestEaseOptions)));
|
||||
|
||||
@ -25,4 +25,5 @@
|
||||
<Content Include="Resources" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
"Active": "Активна",
|
||||
"Inactive": "Не активна",
|
||||
"Activate": "Активировать: /activate_subscription_{SubscriptionId}",
|
||||
"Deactivate": "Деактивировать: /deactivate_subscription_{SubscriptionId}",
|
||||
"Delete": "Удалить: /delete_subscription_{SubscriptionId}"
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"InvalidTimeFormat": "Time <b>{ReceivedTime}</b> does not correspond to the acceptable formats!",
|
||||
"InvalidDateFormat": "Date <b>{ReceivedDate}</b> does not correspond to the acceptable formats!"
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"InvalidTimeFormat": "Время <b>{ReceivedTime}</b> не соответствует допустимым форматам!",
|
||||
"InvalidDateFormat": "Дата <b>{ReceivedDate}</b> не соответствует допустимым форматам!"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Text": "Тип совпадения: <b>{SubscriptionRule}</b>\nШаблон: <b>{Template}</b>\nСообщение: {Link}\n{FromUsername} в @{ChatUsername}"
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Active": "Активна",
|
||||
"Inactive": "Не активна",
|
||||
"Text": "Подписка #{Id}\nЧат: (@{ChatUsername})\nСтатус: {ActiveText}\nПравило: {Rule}\nШаблон: {Template}",
|
||||
|
||||
"ActivateButton": "Активировать",
|
||||
"DeactivateButton": "Деактивировать"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"FailedToActivateSubscription": "Не удалось активировать подписку"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"FailedToDeactivateSubscription": "Не удалось деактивировать подписку"
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"FailedToDeleteSubscription": "Не удалось удалить подписку",
|
||||
"Text": "Подписка #{Id} удалена"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Text": "Привет! Я, Nocr 🤖!"
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Text": "Подписка #{Id} создана",
|
||||
|
||||
"CommandHasWrongFormat": "Команда не удовлетворяет формату",
|
||||
"WrongSubscriptionType": "Не удалось извлечь тип подписки"
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"StartMessage": "Привет! Я, Nocr 🤖!",
|
||||
"TextSubscriptionMatched": "Тип совпадения: <b>{SubscriptionRule}</b>\nШаблон: <b>{Template}</b>\n{FromUsername} в @{ChatUsername}:\n<i>{MessageText}</i>\n\n{Link}"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user