feat: added DI to Client

This commit is contained in:
Pavel-Savely Savianok 2025-05-01 20:50:14 +03:00
parent da0ca92795
commit 786c63166c
8 changed files with 149 additions and 42 deletions

View File

@ -0,0 +1,8 @@
using Telegram.Bot.Types;
namespace JOBot.TClient.Commands;
public interface ITelegramCommand
{
public Task ExecuteAsync(Update update, CancellationToken ct);
}

View File

@ -0,0 +1,18 @@
using JOBot.TClient.Core.Services;
using Telegram.Bot;
using Telegram.Bot.Types;
namespace JOBot.TClient.Commands;
public class StartCommand(ITelegramBotClient bot, UserService userService) : ITelegramCommand
{
public async Task ExecuteAsync(Update update, CancellationToken ct)
{
var isRegistered = await userService.RegisterAsync(
update.Message?.Chat.Id ?? throw new Exception("Chat id is null"),
update.Message.Chat.Username);
await bot.SendMessage(chatId: update.Message.Chat.Id,
isRegistered ? "You registered" : "Not registered", cancellationToken: ct);
}
}

View File

@ -0,0 +1,45 @@
using JOBot.TClient.Commands;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace JOBot.TClient.Core.HostedServices;
using Telegram.Bot;
using Telegram.Bot.Types;
using Microsoft.Extensions.Hosting;
public sealed class BotBackgroundService(
ITelegramBotClient botClient,
IServiceProvider services,
ILogger<BotBackgroundService> logger)
: BackgroundService
{
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
botClient.StartReceiving(
updateHandler: HandleUpdateAsync,
errorHandler: HandleErrorAsync,
cancellationToken: stoppingToken);
return Task.CompletedTask;
}
private async Task HandleUpdateAsync(ITelegramBotClient bot, Update update, CancellationToken ct)
{
using var scope = services.CreateScope();
var commands = new Dictionary<string, ITelegramCommand>
{
["/start"] = scope.ServiceProvider.GetRequiredService<StartCommand>()
};
if (update.Message?.Text is { } text && commands.TryGetValue(text, out var command))
await command.ExecuteAsync(update, ct);
}
private Task HandleErrorAsync(ITelegramBotClient bot, Exception ex, CancellationToken ct)
{
services.CreateScope();
logger.LogError(ex, ex.Message);
return Task.CompletedTask;
}
}

View File

@ -0,0 +1,18 @@
using User = JOBot.Proto.User;
namespace JOBot.TClient.Core.Services;
public class UserService(User.UserClient client)
{
public async Task<bool> RegisterAsync(long userId, string? username)
{
var response = await client.RegisterAsync(new()
{
UserId = userId,
Username = username
});
return response.Success;
}
}

View File

@ -0,0 +1,38 @@
using Grpc.Core;
using Grpc.Net.Client;
using JOBot.Proto;
using JOBot.TClient.Commands;
using JOBot.TClient.Core.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Telegram.Bot;
namespace JOBot.TClient;
public static class DependencyInjection
{
public static IServiceCollection ConfigureServices(this IServiceCollection services, IConfiguration config)
{
services.AddSingleton(config);
services.AddScoped<ChannelBase, GrpcChannel>(_ => GrpcChannel.ForAddress(config.GetValue<string>("BackendHost")
?? throw new MissingFieldException("Host is not defined")));
//Commands
services.AddScoped<StartCommand>();
services.AddSingleton<UserService>();
//gRPC Clients
services.AddScoped<User.UserClient>();
// Telegram Bot
services.AddSingleton<ITelegramBotClient>(_ =>
new TelegramBotClient(config.GetValue<string>("TelegramToken")
?? throw new MissingFieldException("TelegramToken is not set")));
services.AddLogging(builder => builder.AddConsole());
return services;
}
}

View File

@ -16,6 +16,8 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
<PackageReference Include="Telegram.Bot" Version="22.5.1" />
</ItemGroup>
@ -32,4 +34,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Infrastucture\" />
</ItemGroup>
</Project>

View File

@ -1,44 +1,17 @@
using Grpc.Net.Client;
using Proto = JOBot.Proto;
using Telegram.Bot;
using Telegram.Bot.Types;
using Microsoft.Extensions.Configuration;
using JOBot.TClient;
using JOBot.TClient.Core.HostedServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json", true)
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// Настройка DI
services.ConfigureServices(context.Configuration);
// Фоновый сервис для бота
services.AddHostedService<BotBackgroundService>();
})
.Build();
var botClient = new TelegramBotClient(config.GetValue<string>("TelegramToken")
?? throw new MissingFieldException("TelegramToken is not set"));
botClient.StartReceiving(HandleUpdate, HandleError);
Console.WriteLine("Бот запущен. Нажмите Enter для остановки.");
Console.ReadLine();
async Task HandleUpdate(ITelegramBotClient bot, Update update, CancellationToken ct)
{
using var channel = GrpcChannel.ForAddress(config.GetValue<string>("BackendHost")
?? throw new MissingFieldException("Host is not defined"));
var userClient = new Proto.User.UserClient(channel);
if (update.Message?.Text == "/start")
{
var reply = await userClient.RegisterAsync(new Proto.RegisterRequest
{
UserId = update.Message.Chat.Id,
Username = update.Message.Chat.Username ?? ""
});
await bot.SendMessage(
chatId: update.Message.Chat.Id,
text: reply.Success ? "✅ Вы зарегистрированы!" : "❌ Ошибка",
cancellationToken: ct);
}
}
Task HandleError(ITelegramBotClient bot, Exception ex, CancellationToken ct)
{
Console.WriteLine($"Ошибка: {ex.Message}");
return Task.CompletedTask;
}
await host.RunAsync();

View File

@ -1,3 +1,4 @@
{
"TelegramToken": "7372524570:AAGLW5dXhW5Jd78i9Zguyga-5gfeSF9KU4I",
"BackendHost": "http://localhost:5001"
}