diff --git a/Console.Advanced/Abstract/IReceiverService.cs b/Console.Advanced/Abstract/IReceiverService.cs index fb7cee86..5a9a2826 100644 --- a/Console.Advanced/Abstract/IReceiverService.cs +++ b/Console.Advanced/Abstract/IReceiverService.cs @@ -1,4 +1,4 @@ -namespace Telegram.Bot.Abstract; +namespace Console.Advanced.Abstract; /// /// A marker interface for Update Receiver service diff --git a/Console.Advanced/Abstract/PollingServiceBase.cs b/Console.Advanced/Abstract/PollingServiceBase.cs index 1e9650c1..607a87d3 100644 --- a/Console.Advanced/Abstract/PollingServiceBase.cs +++ b/Console.Advanced/Abstract/PollingServiceBase.cs @@ -1,4 +1,4 @@ -namespace Telegram.Bot.Abstract; +namespace Console.Advanced.Abstract; // A background service consuming a scoped service. // See more: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services#consuming-a-scoped-service-in-a-background-task diff --git a/Console.Advanced/Abstract/ReceiverServiceBase.cs b/Console.Advanced/Abstract/ReceiverServiceBase.cs index 2d699dda..25ffccd7 100644 --- a/Console.Advanced/Abstract/ReceiverServiceBase.cs +++ b/Console.Advanced/Abstract/ReceiverServiceBase.cs @@ -1,7 +1,8 @@ +using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Types.Enums; -namespace Telegram.Bot.Abstract; +namespace Console.Advanced.Abstract; /// /// An abstract class to compose Receiver Service and Update Handler classes @@ -34,7 +35,7 @@ public async Task ReceiveAsync(CancellationToken stoppingToken) // ToDo: we can inject ReceiverOptions through IOptions container var receiverOptions = new ReceiverOptions() { - AllowedUpdates = Array.Empty(), + AllowedUpdates = [], DropPendingUpdates = true, }; diff --git a/Console.Advanced/BotConfiguration.cs b/Console.Advanced/BotConfiguration.cs new file mode 100644 index 00000000..1561aba9 --- /dev/null +++ b/Console.Advanced/BotConfiguration.cs @@ -0,0 +1,6 @@ +namespace Console.Advanced; + +public class BotConfiguration +{ + public string BotToken { get; init; } = default!; +} diff --git a/Console.Advanced/Extensions.cs b/Console.Advanced/Extensions.cs deleted file mode 100644 index 7dabfe20..00000000 --- a/Console.Advanced/Extensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.Extensions.Options; - -namespace Microsoft.Extensions.DependencyInjection; - -public static class PollingExtensions -{ - public static T GetConfiguration(this IServiceProvider serviceProvider) - where T : class - { - var o = serviceProvider.GetService>(); - if (o is null) - throw new ArgumentNullException(nameof(T)); - - return o.Value; - } -} diff --git a/Console.Advanced/Program.cs b/Console.Advanced/Program.cs index db591563..f16db557 100644 --- a/Console.Advanced/Program.cs +++ b/Console.Advanced/Program.cs @@ -1,12 +1,13 @@ +using Microsoft.Extensions.Options; using Telegram.Bot; -using Telegram.Bot.Services; +using Console.Advanced; +using Console.Advanced.Services; IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices((context, services) => { // Register Bot configuration - services.Configure( - context.Configuration.GetSection(BotConfiguration.Configuration)); + services.Configure(context.Configuration.GetSection("BotConfiguration")); // Register named HttpClient to benefits from IHttpClientFactory // and consume it with ITelegramBotClient typed client. @@ -16,8 +17,9 @@ services.AddHttpClient("telegram_bot_client").RemoveAllLoggers() .AddTypedClient((httpClient, sp) => { - BotConfiguration? botConfig = sp.GetConfiguration(); - TelegramBotClientOptions options = new(botConfig.BotToken); + BotConfiguration? botConfiguration = sp.GetService>()?.Value; + ArgumentNullException.ThrowIfNull(botConfiguration); + TelegramBotClientOptions options = new(botConfiguration.BotToken); return new TelegramBotClient(options, httpClient); }); @@ -28,14 +30,3 @@ .Build(); await host.RunAsync(); - -#pragma warning disable CA1050 // Declare types in namespaces -#pragma warning disable RCS1110 // Declare type inside namespace. -public class BotConfiguration -#pragma warning restore RCS1110 // Declare type inside namespace. -#pragma warning restore CA1050 // Declare types in namespaces -{ - public static readonly string Configuration = "BotConfiguration"; - - public string BotToken { get; set; } = ""; -} diff --git a/Console.Advanced/Services/PollingService.cs b/Console.Advanced/Services/PollingService.cs index 32b740a6..22d60e38 100644 --- a/Console.Advanced/Services/PollingService.cs +++ b/Console.Advanced/Services/PollingService.cs @@ -1,12 +1,7 @@ -using Telegram.Bot.Abstract; +using Console.Advanced.Abstract; -namespace Telegram.Bot.Services; +namespace Console.Advanced.Services; // Compose Polling and ReceiverService implementations -public class PollingService : PollingServiceBase -{ - public PollingService(IServiceProvider serviceProvider, ILogger logger) - : base(serviceProvider, logger) - { - } -} +public class PollingService(IServiceProvider serviceProvider, ILogger logger) + : PollingServiceBase(serviceProvider, logger); diff --git a/Console.Advanced/Services/ReceiverService.cs b/Console.Advanced/Services/ReceiverService.cs index 5535bba7..ddc5c868 100644 --- a/Console.Advanced/Services/ReceiverService.cs +++ b/Console.Advanced/Services/ReceiverService.cs @@ -1,15 +1,8 @@ -using Telegram.Bot.Abstract; +using Console.Advanced.Abstract; +using Telegram.Bot; -namespace Telegram.Bot.Services; +namespace Console.Advanced.Services; // Compose Receiver and UpdateHandler implementation -public class ReceiverService : ReceiverServiceBase -{ - public ReceiverService( - ITelegramBotClient botClient, - UpdateHandler updateHandler, - ILogger> logger) - : base(botClient, updateHandler, logger) - { - } -} +public class ReceiverService(ITelegramBotClient botClient, UpdateHandler updateHandler, ILogger> logger) + : ReceiverServiceBase(botClient, updateHandler, logger); diff --git a/Console.Advanced/Services/UpdateHandler.cs b/Console.Advanced/Services/UpdateHandler.cs index b6691cc4..fdcfec6c 100644 --- a/Console.Advanced/Services/UpdateHandler.cs +++ b/Console.Advanced/Services/UpdateHandler.cs @@ -1,3 +1,4 @@ +using Telegram.Bot; using Telegram.Bot.Exceptions; using Telegram.Bot.Polling; using Telegram.Bot.Types; @@ -5,23 +6,15 @@ using Telegram.Bot.Types.InlineQueryResults; using Telegram.Bot.Types.ReplyMarkups; -namespace Telegram.Bot.Services; +namespace Console.Advanced.Services; -public class UpdateHandler : IUpdateHandler +public class UpdateHandler(ITelegramBotClient bot, ILogger logger) : IUpdateHandler { - private readonly ITelegramBotClient _bot; - private readonly ILogger _logger; private static readonly InputPollOption[] PollOptions = ["Hello", "World!"]; - public UpdateHandler(ITelegramBotClient bot, ILogger logger) + public async Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, HandleErrorSource source, CancellationToken cancellationToken) { - _bot = bot; - _logger = logger; - } - - public async Task HandleErrorAsync(ITelegramBotClient bot, Exception exception, HandleErrorSource source, CancellationToken cancellationToken) - { - _logger.LogInformation("HandleError: {exception}", exception); + logger.LogInformation("HandleError: {exception}", exception); // Cooldown in case of network connection error if (exception is RequestException) await Task.Delay(TimeSpan.FromSeconds(2)); @@ -49,7 +42,7 @@ public async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, private async Task OnMessage(Message msg) { - _logger.LogInformation("Receive message type: {MessageType}", msg.Type); + logger.LogInformation("Receive message type: {MessageType}", msg.Type); if (msg.Text is not { } messageText) return; @@ -66,7 +59,7 @@ private async Task OnMessage(Message msg) "/throw" => FailingHandler(msg), _ => Usage(msg) }); - _logger.LogInformation("The message was sent with id: {SentMessageId}", sentMessage.MessageId); + logger.LogInformation("The message was sent with id: {SentMessageId}", sentMessage.MessageId); } async Task Usage(Message msg) @@ -83,15 +76,15 @@ async Task Usage(Message msg) /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()); + return await bot.SendTextMessageAsync(msg.Chat, usage, parseMode: ParseMode.Html, replyMarkup: new ReplyKeyboardRemove()); } async Task SendPhoto(Message msg) { - await _bot.SendChatActionAsync(msg.Chat, ChatAction.UploadPhoto); + await bot.SendChatActionAsync(msg.Chat, ChatAction.UploadPhoto); await Task.Delay(2000); // simulate a long task await using var fileStream = new FileStream("Files/bot.gif", FileMode.Open, FileAccess.Read); - return await _bot.SendPhotoAsync(msg.Chat, fileStream, caption: "Read https://telegrambots.github.io/book/"); + return await bot.SendPhotoAsync(msg.Chat, fileStream, caption: "Read https://telegrambots.github.io/book/"); } // Send inline keyboard. You can process responses in OnCallbackQuery handler @@ -105,7 +98,7 @@ async Task SendInlineKeyboard(Message msg) InlineKeyboardButton.WithUrl("WithUrl", "https://github.com/TelegramBots/Telegram.Bot") ], ]; - return await _bot.SendTextMessageAsync(msg.Chat, "Inline buttons:", replyMarkup: new InlineKeyboardMarkup(buttons)); + return await bot.SendTextMessageAsync(msg.Chat, "Inline buttons:", replyMarkup: new InlineKeyboardMarkup(buttons)); } async Task SendReplyKeyboard(Message msg) @@ -115,12 +108,12 @@ async Task SendReplyKeyboard(Message msg) ["1.1", "1.2", "1.3"], ["2.1", "2.2"], ]; - return await _bot.SendTextMessageAsync(msg.Chat, "Keyboard buttons:", replyMarkup: new ReplyKeyboardMarkup(keys) { ResizeKeyboard = true }); + return await bot.SendTextMessageAsync(msg.Chat, "Keyboard buttons:", replyMarkup: new ReplyKeyboardMarkup(keys) { ResizeKeyboard = true }); } async Task RemoveKeyboard(Message msg) { - return await _bot.SendTextMessageAsync(msg.Chat, "Removing keyboard", replyMarkup: new ReplyKeyboardRemove()); + return await bot.SendTextMessageAsync(msg.Chat, "Removing keyboard", replyMarkup: new ReplyKeyboardRemove()); } async Task RequestContactAndLocation(Message msg) @@ -130,24 +123,24 @@ async Task RequestContactAndLocation(Message msg) KeyboardButton.WithRequestLocation("Location"), KeyboardButton.WithRequestContact("Contact"), ]; - return await _bot.SendTextMessageAsync(msg.Chat, "Who or Where are you?", replyMarkup: new ReplyKeyboardMarkup(buttons)); + return await bot.SendTextMessageAsync(msg.Chat, "Who or Where are you?", replyMarkup: new ReplyKeyboardMarkup(buttons)); } async Task StartInlineQuery(Message msg) { var button = InlineKeyboardButton.WithSwitchInlineQueryCurrentChat("Inline Mode"); - return await _bot.SendTextMessageAsync(msg.Chat, "Press the button to start Inline Query\n\n" + + 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 SendPoll(Message msg) { - return await _bot.SendPollAsync(msg.Chat, "Question", PollOptions, isAnonymous: false); + return await bot.SendPollAsync(msg.Chat, "Question", PollOptions, isAnonymous: false); } async Task SendAnonymousPoll(Message msg) { - return await _bot.SendPollAsync(chatId: msg.Chat, "Question", PollOptions); + return await bot.SendPollAsync(chatId: msg.Chat, "Question", PollOptions); } static Task FailingHandler(Message msg) @@ -158,35 +151,35 @@ static Task FailingHandler(Message msg) // 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}"); + 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); + 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); + 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}"); + 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}"); + logger.LogInformation($"Received Pull info: {poll.Question}"); return Task.CompletedTask; } @@ -194,12 +187,12 @@ 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"); + 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); + logger.LogInformation("Unknown update type: {UpdateType}", update.Type); return Task.CompletedTask; } } diff --git a/Webhook.Controllers/BotConfiguration.cs b/Webhook.Controllers/BotConfiguration.cs index 8ecb54a0..f4dd7785 100644 --- a/Webhook.Controllers/BotConfiguration.cs +++ b/Webhook.Controllers/BotConfiguration.cs @@ -1,3 +1,5 @@ +namespace Webhook.Controllers; + public class BotConfiguration { public string BotToken { get; init; } = default!; diff --git a/Webhook.Controllers/Program.cs b/Webhook.Controllers/Program.cs index 5c5744ce..9d236328 100644 --- a/Webhook.Controllers/Program.cs +++ b/Webhook.Controllers/Program.cs @@ -1,4 +1,5 @@ using Telegram.Bot; +using Webhook.Controllers; var builder = WebApplication.CreateBuilder(args); diff --git a/Webhook.MinimalAPIs/Program.cs b/Webhook.MinimalAPIs/Program.cs index decf9834..ce1553ed 100644 --- a/Webhook.MinimalAPIs/Program.cs +++ b/Webhook.MinimalAPIs/Program.cs @@ -2,8 +2,8 @@ using Telegram.Bot.Types; var builder = WebApplication.CreateBuilder(args); -var token = builder.Configuration.GetValue("BotToken", "{set your bot token in appsettings.json")!; -var webhookUrl = builder.Configuration.GetValue("BotWebhookUrl", "{set your bot webhook url in appsettings.json")!; +var token = builder.Configuration["BotToken"]!; // set your bot token in appsettings.json +var webhookUrl = builder.Configuration["BotWebhookUrl"]!; // set your bot webhook public url in appsettings.json builder.Services.ConfigureTelegramBot(opt => opt.SerializerOptions); builder.Services.AddHttpClient("tgwebhook").RemoveAllLoggers().AddTypedClient(httpClient => new TelegramBotClient(token, httpClient));