refactor: extract commands

This commit is contained in:
Guillermo Marcel 2025-03-26 15:41:39 -03:00
parent 2b33a596d6
commit ba1021c5e6
3 changed files with 95 additions and 71 deletions

View File

@ -0,0 +1,12 @@
using System.Net.Mime;
using Telegram.Bots.Types;
namespace CasaBotApp;
public class BotCommand
{
public string Command { get; set; } = "/example";
public string Description { get; set; } = "Start the bot";
public Func<Message, string, Task<Response<TextMessage>>> Responder { get; set; } = (_, _) => Task.FromResult<Response<TextMessage>>(null);
public Func<TextMessage, BotCommand, Task>? Action { get; set; }
}

View File

@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Text;
using System.Xml.Schema; using System.Xml.Schema;
using Telegram.Bots; using Telegram.Bots;
using Telegram.Bots.Extensions.Polling; using Telegram.Bots.Extensions.Polling;
@ -14,6 +15,7 @@ public class BotHandler : IUpdateHandler
private readonly ILogger<BotHandler> _logger; private readonly ILogger<BotHandler> _logger;
private readonly TelegramOptions _telegramOptions; private readonly TelegramOptions _telegramOptions;
private readonly List<Chat> _subscribers = []; private readonly List<Chat> _subscribers = [];
private readonly Dictionary<string, BotCommand> _commands;
private readonly IBotClient _bot; private readonly IBotClient _bot;
@ -22,6 +24,27 @@ public class BotHandler : IUpdateHandler
_logger = logger; _logger = logger;
_telegramOptions = telegramConfiguration.Value; _telegramOptions = telegramConfiguration.Value;
_bot = bot; _bot = bot;
_commands = [];
RegisterCommand(new()
{
Command = "/register",
Description = "Register to receive messages on every update",
Action = RegisterUser,
Responder = Respond
});
RegisterCommand(new()
{
Command = "/photo",
Description = "Get a photo",
Action = SendImageTest,
Responder = Respond
});
}
public void RegisterCommand(BotCommand command)
{
command.Responder = Respond;
_commands[command.Command] = command;
} }
@ -149,11 +172,11 @@ public class BotHandler : IUpdateHandler
} }
} }
private async Task SendImageTest(long id) private async Task SendImageTest(TextMessage msg, BotCommand _)
{ {
await using var stream = File.OpenRead(@"C:\Users\GuillermoMarcel\Pictures\prueba.jpeg"); await using var stream = File.OpenRead(@"C:\Users\GuillermoMarcel\Pictures\prueba.jpeg");
var send = new SendPhotoFile(id.ToString(), stream); var send = new SendPhotoFile(msg.Chat.Id.ToString(), stream);
await _bot.HandleAsync(send); await _bot.HandleAsync(send);
} }
@ -161,10 +184,34 @@ public class BotHandler : IUpdateHandler
private async Task OnMessage(TextMessage msg) private async Task OnMessage(TextMessage msg)
{ {
if(!_commands.TryGetValue(msg.Text, out var command))
switch (msg.Text) {
await SendHelp(msg);
return;
}
if (command?.Action is null)
{
_logger.LogError("Command {Command} has no action", msg.Text);
}
await command!.Action!(msg, command);
}
private async Task SendHelp(TextMessage msg)
{
_logger.LogInformation("Received '{Text}' in {Chat}", msg.Text, msg.Chat);
var message = new StringBuilder();
message.AppendLine("Commands:");
foreach (var command in _commands.Values)
{
message.AppendLine($"{command.Command} - {command.Description}");
}
await Respond(msg, message.ToString());
}
private async Task RegisterUser(TextMessage msg, BotCommand _)
{ {
case "/register":
if (_subscribers.Any(c => c.Id == msg.Chat.Id)) if (_subscribers.Any(c => c.Id == msg.Chat.Id))
{ {
await Respond(msg, "You are already registered to receive messages"); await Respond(msg, "You are already registered to receive messages");
@ -174,25 +221,6 @@ public class BotHandler : IUpdateHandler
_subscribers.Add(msg.Chat); _subscribers.Add(msg.Chat);
_logger.LogInformation("User {User} ({id}) registered to receive messages", msg.Chat.FirstName, msg.Chat.Id); _logger.LogInformation("User {User} ({id}) registered to receive messages", msg.Chat.FirstName, msg.Chat.Id);
await Respond(msg, "You are registered to receive messages every minute"); await Respond(msg, "You are registered to receive messages every minute");
return;
case "/photo":
await SendImageTest(msg.Chat.Id);
return;
case "/soyandre":
await Respond(msg, "Hola vida, te amo mucho ❤️");
return;
default:
_logger.LogInformation("Received '{Text}' in {Chat}", msg.Text, msg.Chat);
const string commands =
"Commands: \n/help to show the commands \n/register to get messages every minute \n/photo to get a photo \n/soyandre por si sos andre";
await Respond(msg, commands);
break;
}
} }

View File

@ -1,13 +1,14 @@
using AutoScan; using AutoScan;
using AutoScan.Options; using AutoScan.Options;
using CasaBotApp; using CasaBotApp;
using CasaBotApp.Extensions;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bots; using Telegram.Bots;
using Telegram.Bots.Extensions.Polling; using Telegram.Bots.Extensions.Polling;
using Telegram.Bots.Http;
var environment = Environment.GetEnvironmentVariable("CASABOT_ENVIRONMENT"); var environment = Environment.GetEnvironmentVariable("CASABOT_ENVIRONMENT");
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
@ -20,17 +21,8 @@ var hostBuilder = new HostBuilder();
hostBuilder.ConfigureServices((_, services) => hostBuilder.ConfigureServices((_, services) =>
{ {
services.AddSingleton(configuration); services.AddSingleton(configuration);
services.AddLogging(builder =>
{ services.AddLogging(configuration);
builder.AddConfiguration(configuration.GetSection("Logging"));
//add time to logs
builder.AddSimpleConsole(options =>
{
options.IncludeScopes = true;
options.SingleLine = true;
options.TimestampFormat = "[HH:mm:ss] ";
});
});
services.Configure<TelegramOptions>(configuration.GetSection("Telegram")); services.Configure<TelegramOptions>(configuration.GetSection("Telegram"));
services.Configure<AutoScanOptions>(configuration.GetSection("AutoScan")); services.Configure<AutoScanOptions>(configuration.GetSection("AutoScan"));
@ -44,8 +36,19 @@ hostBuilder.ConfigureServices((_, services) =>
services.AddSingleton<IUpdateHandler>(sp => sp.GetService<BotHandler>()!); services.AddSingleton<IUpdateHandler>(sp => sp.GetService<BotHandler>()!);
// To get notifications when a retry is performed
services.AddAutoScan(); services.AddAutoScan();
services.AddHttpClient();
services.AddPolicyRegistry().Add("RetryPolicy", RetryPolicyExtension.GetRetryPolicy());
services.AddHttpClient<IBotClient, BotClient>().AddPolicyHandler(RetryPolicyExtension.GetRetryPolicy());
services.Configure<HostOptions>(hostOptions =>
{
hostOptions.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
});
}); });
@ -56,39 +59,20 @@ var logger = host.Services.GetService<ILogger<Program>>()!;
var botHandler = host.Services.GetService<BotHandler>()!; var botHandler = host.Services.GetService<BotHandler>()!;
var autoScanApp = host.Services.GetService<AutoScanApp>()!; var autoScanApp = host.Services.GetService<AutoScanApp>()!;
CommandRegister.RegisterCommands(botHandler, autoScanApp);
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
_ = autoScanApp.Run(cts.Token); _ = autoScanApp.Run(cts.Token);
botHandler.Start(cts.Token); botHandler.Start(cts.Token);
autoScanApp.OnScanCompleted = async options => CommandRegister.UpdateOnScanCompleted(botHandler, autoScanApp, logger);
{
logger.LogInformation("Scan completed at {At}", DateTime.Now);
try
{
//list all the images in the detection folder
if (options.Scanner?.DetectionFolder is null)
return;
var images = Directory.GetFiles(options.Scanner.DetectionFolder , "*.jpg");
botHandler.Update($"Scan completed, found {images.Length} images");
botHandler.UpdatePhotos(images);
}catch(Exception ex)
{
logger.LogError(ex, "Error while sending message");
}
};
_ = host.RunAsync(cts.Token);
logger.LogInformation("Bot started"); logger.LogInformation("Bot started");
logger.LogInformation("Press any key to stop the bot..."); await host.RunAsync(cts.Token);
Console.ReadLine();
await cts.CancelAsync(); // stop the bot await cts.CancelAsync(); // stop the bot
return;