diff --git a/src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs b/src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs index 5b2e281..ca50479 100644 --- a/src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs +++ b/src/Nocr.TelegramClient.AppServices/Bots/NocrCallbackData.cs @@ -8,6 +8,11 @@ public class NocrCallbackData : CallbackData { } + public static NocrCallbackData Start() + { + return new NocrCallbackData(NocrState.Start); + } + public static NocrCallbackData ActivateSubscription(long subscriptionId) { return new NocrCallbackData(NocrState.ActivateSubscription, subscriptionId.ToString()); @@ -29,4 +34,9 @@ public class NocrCallbackData : CallbackData new NocrCallbackData(NocrState.ViewSubscription, subscriptionId.Value.ToString()): new NocrCallbackData(NocrState.ViewSubscription); } + + public static NocrCallbackData Feedback() + { + return new NocrCallbackData(NocrState.Feedback); + } } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs b/src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs index 9ff60d0..5188fed 100644 --- a/src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs +++ b/src/Nocr.TelegramClient.AppServices/Bots/NocrState.cs @@ -9,5 +9,6 @@ public enum NocrState // States Start, - ViewSubscription + ViewSubscription, + Feedback } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/StartHandlerBase.cs b/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/StartHandlerBase.cs index cfe4fd8..660e534 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/StartHandlerBase.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/StartHandlerBase.cs @@ -4,7 +4,6 @@ using Insight.TelegramBot.Keyboards; using Insight.TelegramBot.Models; using Nocr.TelegramClient.AppServices.Bots; using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; -using Nocr.TelegramClient.AppServices.Handlers.Messages.StartMessage; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.ReplyMarkups; @@ -63,6 +62,11 @@ public abstract class StartHandlerBase { CallbackData = NocrCallbackData.ViewSubscription().ToString() }); + + markup.Add(new InlineKeyboardButton(Localizer.Get(nameof(StartHandlerBase), "FeedbackButton")) + { + CallbackData = NocrCallbackData.Feedback().ToString() + }); return markup.InlineKeyboardMarkup; } diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/ViewSubscriptionHandlerBase.cs b/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/ViewSubscriptionHandlerBase.cs index 56baa75..73736eb 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/ViewSubscriptionHandlerBase.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/BaseHandlers/ViewSubscriptionHandlerBase.cs @@ -158,7 +158,7 @@ public abstract class ViewSubscriptionHandlerBase markup.Add(new InlineKeyboardButton(Localizer.Get("Buttons", "Back")) { - CallbackData = new NocrCallbackData(NocrState.Start).ToString() + CallbackData = NocrCallbackData.Start().ToString() }); return markup; diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackHandler.cs b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackHandler.cs new file mode 100644 index 0000000..fe7a9ca --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackHandler.cs @@ -0,0 +1,39 @@ +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 Telegram.Bot.Types; +using Telegram.Bot.Types.ReplyMarkups; + +namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.Feedback; + +public class FeedbackHandler : IMatchingUpdateHandler +{ + private readonly ILogger _logger; + private readonly ILocalizer _localizer; + private readonly IBot _bot; + + public FeedbackHandler(ILogger logger, ILocalizer localizer, IBot bot) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); + _bot = bot ?? throw new ArgumentNullException(nameof(bot)); + } + + public Task Handle(Update update, CancellationToken cancellationToken = default) + { + // TODO: Check, that other messages sent to chat, no to one, who clicks + var message = new TextMessage(update.CallbackQuery.Message.Chat.Id) + { + Text = _localizer.Get(nameof(FeedbackHandler), "Text"), + ReplyMarkup = new InlineKeyboardMarkup(new InlineKeyboardButton(_localizer.Get("buttons", "back")) + { + CallbackData = NocrCallbackData.Start().ToString() + }) + }; + + return _bot.EditOrSendTextMessage(update.CallbackQuery.Message.MessageId, message, _logger, cancellationToken); + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackMatcher.cs b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackMatcher.cs new file mode 100644 index 0000000..fd4606c --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/Feedback/FeedbackMatcher.cs @@ -0,0 +1,12 @@ +using Insight.TelegramBot.Handling.Matchers.CallbackQueryMatchers; +using Nocr.TelegramClient.AppServices.Bots; + +namespace Nocr.TelegramClient.AppServices.Handlers.CallbackQueries.Feedback; + +public sealed class FeedbackMatcher : StateCallbackQueryMatcher +{ + public FeedbackMatcher() + { + ExpectingState = NocrState.Feedback; + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/ViewSubscription/ViewSubscriptionHandler.cs b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/ViewSubscription/ViewSubscriptionHandler.cs index c334ecf..7ed5715 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/ViewSubscription/ViewSubscriptionHandler.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/CallbackQueries/ViewSubscription/ViewSubscriptionHandler.cs @@ -1,7 +1,6 @@ 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; diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageHandler.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageHandler.cs new file mode 100644 index 0000000..673834f --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageHandler.cs @@ -0,0 +1,76 @@ +using FormatWith; +using Insight.Localizer; +using Insight.TelegramBot.Handling.Handlers; +using Insight.TelegramBot.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Nocr.TelegramClient.AppServices.Bots; +using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; +using Nocr.TelegramClient.AppServices.Options; +using Telegram.Bot.Types; +using Telegram.Bot.Types.ReplyMarkups; + +namespace Nocr.TelegramClient.AppServices.Handlers.Messages.FeedbackMessage; + +public sealed class FeedbackMessageHandler : IMatchingUpdateHandler +{ + private readonly ILogger _logger; + private readonly ILocalizer _localizer; + private readonly IMessageDispatcherQueue _messageDispatcherQueue; + private readonly AdministrationOptions _administrationOptions; + + public FeedbackMessageHandler(ILogger logger, ILocalizer localizer, + IMessageDispatcherQueue messageDispatcherQueue, IOptionsSnapshot administrationOptions) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); + _messageDispatcherQueue = + messageDispatcherQueue ?? throw new ArgumentNullException(nameof(messageDispatcherQueue)); + _administrationOptions = + administrationOptions.Value ?? throw new ArgumentNullException(nameof(administrationOptions)); + } + + public Task Handle(Update update, CancellationToken cancellationToken = default) + { + var from = update.Message.From; + var feedbackText = update.Message.Text + .Replace("/feedback", string.Empty) + .Trim(' '); + + var message = new TextMessage(from.Id) + { + Text = _localizer.Get(nameof(FeedbackMessageHandler), "Text"), + ReplyMarkup = new InlineKeyboardMarkup(new InlineKeyboardButton(_localizer.Get("buttons", "back")) + { + CallbackData = NocrCallbackData.Start().ToString() + }) + }; + + _messageDispatcherQueue.Enqueue(message); + + foreach (var feedbackReceiverId in _administrationOptions.FeedbackReceiverIds) + { + var feedbackMessage = new TextMessage(feedbackReceiverId) + { + Text = _localizer.Get(nameof(FeedbackMessageHandler), "FeedbackText") + .FormatWith(new + { + FromId = from.Id, + FromUsername = string.IsNullOrWhiteSpace(from.Username) ? "anonymous" : $"@{from.Username}", + Text = feedbackText + }) + }; + + try + { + _messageDispatcherQueue.Enqueue(feedbackMessage); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to send feedback message to {FeedbackReceiverId}", feedbackReceiverId); + } + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageMatcher.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageMatcher.cs new file mode 100644 index 0000000..4b57c63 --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/FeedbackMessage/FeedbackMessageMatcher.cs @@ -0,0 +1,11 @@ +using Insight.TelegramBot.Handling.Matchers.TextMatchers; + +namespace Nocr.TelegramClient.AppServices.Handlers.Messages.FeedbackMessage; + +public sealed class FeedbackMessageMatcher : TextStartWithUpdateMatcher +{ + public FeedbackMessageMatcher() + { + Template = "/feedback"; + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Options/AdministrationOptions.cs b/src/Nocr.TelegramClient.AppServices/Options/AdministrationOptions.cs new file mode 100644 index 0000000..cb08d5d --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Options/AdministrationOptions.cs @@ -0,0 +1,14 @@ +namespace Nocr.TelegramClient.AppServices.Options; + +public sealed class AdministrationOptions +{ + /// + /// Список telegram идентификаторов для получения отзывов + /// + public long[] FeedbackReceiverIds { get; set; } = Array.Empty(); + + /// + /// Список telegram идентификаторов для получения обновлений + /// + public long[] UpdateReceiverIds { get; set; } = Array.Empty(); +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs index f3deca6..774676a 100644 --- a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs +++ b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; +using Nocr.TelegramClient.AppServices.Handlers.Messages.FeedbackMessage; using Nocr.TelegramClient.AppServices.Options; using Nocr.TelegramClient.AppServices.TextSubscriptions.Handlers; using Nocr.TelegramClient.AppServices.Users; @@ -23,6 +24,8 @@ public static class ServiceCollectionExtensions services.AddRebusHandler(); services.AddHttpClient(); + services.Configure(configuration.GetSection(nameof(AdministrationOptions))); + services.Configure(configuration.GetSection(nameof(UsersRestEaseOptions))); services.AddScoped(ctx => { diff --git a/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Base/StartHandlerBase/StartHandlerBase.ru-ru.json b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Base/StartHandlerBase/StartHandlerBase.ru-ru.json index f0a1a99..441aa6e 100644 --- a/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Base/StartHandlerBase/StartHandlerBase.ru-ru.json +++ b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Base/StartHandlerBase/StartHandlerBase.ru-ru.json @@ -1,5 +1,6 @@ { "Text": "Привет! Я, Nocr 🤖!", - "SubscriptionsButton": "Подписки 📩" + "SubscriptionsButton": "Подписки 📩", + "FeedbackButton": "Оставить отзыв 🙋‍" } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/CallbackQueries/Feedback/FeedbackHandler.ru-ru.json b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/CallbackQueries/Feedback/FeedbackHandler.ru-ru.json new file mode 100644 index 0000000..59ede4a --- /dev/null +++ b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/CallbackQueries/Feedback/FeedbackHandler.ru-ru.json @@ -0,0 +1,3 @@ +{ + "Text": "Чтобы оставить отзыв или пожелание по улучшению отправьте команду /feedback в формате `/feedback текст отзыва`. Например, /feeback Классный бот! Спасибо!" +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Messages/FeedbackMessage/FeedbackMessageHandler.ru-ru.json b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Messages/FeedbackMessage/FeedbackMessageHandler.ru-ru.json new file mode 100644 index 0000000..e8f4717 --- /dev/null +++ b/src/Nocr.TelegramClient.Host/Resources/Handlers/TelegramHandlers/Messages/FeedbackMessage/FeedbackMessageHandler.ru-ru.json @@ -0,0 +1,5 @@ +{ + "Text": "Благодарим за отзыв!", + + "FeedbackText": "#feedback\nПолучен отзыв от: {FromId} ({FromUsername})\n{Text}" +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Host/appsettings.json b/src/Nocr.TelegramClient.Host/appsettings.json index 1947392..9a81d53 100644 --- a/src/Nocr.TelegramClient.Host/appsettings.json +++ b/src/Nocr.TelegramClient.Host/appsettings.json @@ -22,5 +22,13 @@ "Path": "Resources", "Pattern": "", "ReadNestedFolders": "true" + }, + "AdministrationOptions": { + "FeedbackReceiverIds": [ + -4202454237 + ], + "UpdateReceiverIds": [ + -4202454237 + ] } }