-
Notifications
You must be signed in to change notification settings - Fork 296
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Webhook.Controllers (STJ) & harmonize with Console.Advanced
- Loading branch information
Showing
9 changed files
with
233 additions
and
288 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
using Telegram.Bot.Exceptions; | ||
using Telegram.Bot.Polling; | ||
using Telegram.Bot.Types; | ||
using Telegram.Bot.Types.Enums; | ||
using Telegram.Bot.Types.InlineQueryResults; | ||
using Telegram.Bot.Types.ReplyMarkups; | ||
|
||
namespace Telegram.Bot.Services; | ||
|
||
public class UpdateHandler | ||
{ | ||
private readonly ITelegramBotClient _bot; | ||
private readonly ILogger<UpdateHandler> _logger; | ||
private static readonly InputPollOption[] PollOptions = ["Hello", "World!"]; | ||
|
||
public UpdateHandler(ITelegramBotClient bot, ILogger<UpdateHandler> logger) | ||
{ | ||
_bot = bot; | ||
_logger = logger; | ||
} | ||
|
||
public async Task HandleErrorAsync(Exception exception, HandleErrorSource source, CancellationToken cancellationToken) | ||
{ | ||
_logger.LogInformation("HandleError: {exception}", exception); | ||
Check warning on line 24 in Webhook.Controllers/Services/UpdateHandler.cs GitHub Actions / build
|
||
// Cooldown in case of network connection error | ||
if (exception is RequestException) | ||
await Task.Delay(TimeSpan.FromSeconds(2)); | ||
Check warning on line 27 in Webhook.Controllers/Services/UpdateHandler.cs GitHub Actions / build
|
||
} | ||
|
||
public async Task HandleUpdateAsync(Update update, CancellationToken cancellationToken) | ||
{ | ||
cancellationToken.ThrowIfCancellationRequested(); | ||
await (update switch | ||
{ | ||
{ Message: { } message } => OnMessage(message), | ||
{ EditedMessage: { } message } => OnMessage(message), | ||
{ CallbackQuery: { } callbackQuery } => OnCallbackQuery(callbackQuery), | ||
{ InlineQuery: { } inlineQuery } => OnInlineQuery(inlineQuery), | ||
{ ChosenInlineResult: { } chosenInlineResult } => OnChosenInlineResult(chosenInlineResult), | ||
{ Poll: { } poll } => OnPoll(poll), | ||
{ PollAnswer: { } pollAnswer } => OnPollAnswer(pollAnswer), | ||
// UpdateType.ChannelPost: | ||
// UpdateType.EditedChannelPost: | ||
// UpdateType.ShippingQuery: | ||
// UpdateType.PreCheckoutQuery: | ||
_ => UnknownUpdateHandlerAsync(update) | ||
}); | ||
} | ||
|
||
private async Task OnMessage(Message msg) | ||
{ | ||
_logger.LogInformation("Receive message type: {MessageType}", msg.Type); | ||
Check warning on line 52 in Webhook.Controllers/Services/UpdateHandler.cs GitHub Actions / build
|
||
if (msg.Text is not { } messageText) | ||
return; | ||
|
||
Message sentMessage = await (messageText.Split(' ')[0] switch | ||
{ | ||
"/photo" => SendPhoto(msg), | ||
"/inline_buttons" => SendInlineKeyboard(msg), | ||
"/keyboard" => SendReplyKeyboard(msg), | ||
"/remove" => RemoveKeyboard(msg), | ||
"/request" => RequestContactAndLocation(msg), | ||
"/inline_mode" => StartInlineQuery(msg), | ||
"/poll" => SendPoll(msg), | ||
"/poll_anonymous" => SendAnonymousPoll(msg), | ||
"/throw" => FailingHandler(msg), | ||
_ => Usage(msg) | ||
}); | ||
_logger.LogInformation("The message was sent with id: {SentMessageId}", sentMessage.MessageId); | ||
Check warning on line 69 in Webhook.Controllers/Services/UpdateHandler.cs GitHub Actions / build
|
||
} | ||
|
||
async Task<Message> Usage(Message msg) | ||
{ | ||
const string usage = """ | ||
<b><u>Bot menu</u></b>: | ||
/photo - send a photo | ||
/inline_buttons - send inline buttons | ||
/keyboard - send keyboard buttons | ||
/remove - remove keyboard buttons | ||
/request - request location or contact | ||
/inline_mode - send inline-mode results list | ||
/poll - send a poll | ||
/poll_anonymous - send an anonymous poll | ||
/throw - what happens if handler fails | ||
"""; | ||
return await _bot.SendTextMessageAsync(msg.Chat, usage, parseMode: ParseMode.Html, replyMarkup: new ReplyKeyboardRemove()); | ||
} | ||
|
||
async Task<Message> SendPhoto(Message msg) | ||
{ | ||
await _bot.SendChatActionAsync(msg.Chat, ChatAction.UploadPhoto); | ||
await Task.Delay(2000); // simulate a long task | ||
await using var fileStream = new FileStream("Files/tux.png", FileMode.Open, FileAccess.Read); | ||
return await _bot.SendPhotoAsync(msg.Chat, fileStream, caption: "Read https://telegrambots.github.io/book/"); | ||
} | ||
|
||
// Send inline keyboard. You can process responses in OnCallbackQuery handler | ||
async Task<Message> SendInlineKeyboard(Message msg) | ||
{ | ||
List<List<InlineKeyboardButton>> buttons = | ||
[ | ||
["1.1", "1.2", "1.3"], | ||
[ | ||
InlineKeyboardButton.WithCallbackData("WithCallbackData", "CallbackData"), | ||
InlineKeyboardButton.WithUrl("WithUrl", "https://github.com/TelegramBots/Telegram.Bot") | ||
], | ||
]; | ||
return await _bot.SendTextMessageAsync(msg.Chat, "Inline buttons:", replyMarkup: new InlineKeyboardMarkup(buttons)); | ||
} | ||
|
||
async Task<Message> SendReplyKeyboard(Message msg) | ||
{ | ||
List<List<KeyboardButton>> keys = | ||
[ | ||
["1.1", "1.2", "1.3"], | ||
["2.1", "2.2"], | ||
]; | ||
return await _bot.SendTextMessageAsync(msg.Chat, "Keyboard buttons:", replyMarkup: new ReplyKeyboardMarkup(keys) { ResizeKeyboard = true }); | ||
} | ||
|
||
async Task<Message> RemoveKeyboard(Message msg) | ||
{ | ||
return await _bot.SendTextMessageAsync(msg.Chat, "Removing keyboard", replyMarkup: new ReplyKeyboardRemove()); | ||
} | ||
|
||
async Task<Message> RequestContactAndLocation(Message msg) | ||
{ | ||
List<KeyboardButton> buttons = | ||
[ | ||
KeyboardButton.WithRequestLocation("Location"), | ||
KeyboardButton.WithRequestContact("Contact"), | ||
]; | ||
return await _bot.SendTextMessageAsync(msg.Chat, "Who or Where are you?", replyMarkup: new ReplyKeyboardMarkup(buttons)); | ||
} | ||
|
||
async Task<Message> StartInlineQuery(Message msg) | ||
{ | ||
var button = InlineKeyboardButton.WithSwitchInlineQueryCurrentChat("Inline Mode"); | ||
return await _bot.SendTextMessageAsync(msg.Chat, "Press the button to start Inline Query\n\n" + | ||
"(Make sure you enabled Inline Mode in @BotFather)", replyMarkup: new InlineKeyboardMarkup(button)); | ||
} | ||
|
||
async Task<Message> SendPoll(Message msg) | ||
{ | ||
return await _bot.SendPollAsync(msg.Chat, "Question", PollOptions, isAnonymous: false); | ||
} | ||
|
||
async Task<Message> SendAnonymousPoll(Message msg) | ||
{ | ||
return await _bot.SendPollAsync(chatId: msg.Chat, "Question", PollOptions); | ||
} | ||
|
||
static Task<Message> FailingHandler(Message msg) | ||
{ | ||
throw new IndexOutOfRangeException(); | ||
} | ||
|
||
// Process Inline Keyboard callback data | ||
private async Task OnCallbackQuery(CallbackQuery callbackQuery) | ||
{ | ||
_logger.LogInformation("Received inline keyboard callback from: {CallbackQueryId}", callbackQuery.Id); | ||
await _bot.AnswerCallbackQueryAsync(callbackQuery.Id, $"Received {callbackQuery.Data}"); | ||
await _bot.SendTextMessageAsync(callbackQuery.Message!.Chat, $"Received {callbackQuery.Data}"); | ||
} | ||
|
||
#region Inline Mode | ||
|
||
private async Task OnInlineQuery(InlineQuery inlineQuery) | ||
{ | ||
_logger.LogInformation("Received inline query from: {InlineQueryFromId}", inlineQuery.From.Id); | ||
|
||
InlineQueryResult[] results = [ // displayed result | ||
new InlineQueryResultArticle("1", "Telegram.Bot", new InputTextMessageContent("hello")), | ||
new InlineQueryResultArticle("2", "is the best", new InputTextMessageContent("world")) | ||
]; | ||
await _bot.AnswerInlineQueryAsync(inlineQuery.Id, results, cacheTime: 0, isPersonal: true); | ||
} | ||
|
||
private async Task OnChosenInlineResult(ChosenInlineResult chosenInlineResult) | ||
{ | ||
_logger.LogInformation("Received inline result: {ChosenInlineResultId}", chosenInlineResult.ResultId); | ||
await _bot.SendTextMessageAsync(chosenInlineResult.From.Id, $"You chose result with Id: {chosenInlineResult.ResultId}"); | ||
} | ||
|
||
#endregion | ||
|
||
private Task OnPoll(Poll poll) | ||
{ | ||
_logger.LogInformation($"Received Pull info: {poll.Question}"); | ||
return Task.CompletedTask; | ||
} | ||
|
||
private async Task OnPollAnswer(PollAnswer pollAnswer) | ||
{ | ||
var answer = pollAnswer.OptionIds.FirstOrDefault(); | ||
var selectedOption = PollOptions[answer]; | ||
await _bot.SendTextMessageAsync(pollAnswer.User.Id, $"You've chosen: {selectedOption.Text} in poll"); | ||
} | ||
|
||
private Task UnknownUpdateHandlerAsync(Update update) | ||
{ | ||
_logger.LogInformation("Unknown update type: {UpdateType}", update.Type); | ||
return Task.CompletedTask; | ||
} | ||
} |
Oops, something went wrong.