feat: implemented registration stage of preparation on PrepareUserState

implemented auth, added auth tools AcceptNotPreparedAttribute.cs, IAuthorizedTelegramCommand.cs
This commit is contained in:
Pavel-Savely Savianok 2025-07-12 01:52:16 +03:00
parent 67a3457f2d
commit a526dbf6c6
11 changed files with 80 additions and 12 deletions

View File

@ -1,17 +1,20 @@
using JOBot.Proto;
using JOBot.TClient.Infrastructure.Attributes.Authorization;
using JOBot.TClient.Services;
using JOBot.TClient.Statements;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
namespace JOBot.TClient.Commands.Buttons;
public class EulaAgreementButtonCommand(PrepareUserService prepareUserService) : IAuthorizedTelegramCommand
[AcceptNotPrepared]
public class EulaAgreementButtonCommand(PrepareUserState prepareUserState) : IAuthorizedTelegramCommand
{
public async Task ExecuteAsync(Update update, GetUserResponse user, CancellationToken ct)
{
if (update.Type != UpdateType.Message || update.Message?.From == null)
return;
await prepareUserService.AcceptEula(update, ct);
await prepareUserState.AcceptEula(update, ct);
}
}

View File

@ -0,0 +1,14 @@
using Telegram.Bot;
using Telegram.Bot.Types;
namespace JOBot.TClient.Commands;
public class InfoCommand(ITelegramBotClient bot) : ITelegramCommand
{
public async Task ExecuteAsync(Update update, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(update.Message?.From);
await bot.SendMessage(update.Message.From.Id, TextResource.Info, cancellationToken: ct);
}
}

View File

@ -0,0 +1,13 @@
using JOBot.Proto;
using JOBot.TClient.Services;
using Telegram.Bot.Types;
namespace JOBot.TClient.Commands;
public class MenuCommand(MenuService menuService) : IAuthorizedTelegramCommand
{
public async Task ExecuteAsync(Update update, GetUserResponse user, CancellationToken ct)
{
await menuService.RenderMenu(update, ct);
}
}

View File

@ -1,5 +1,7 @@
using JOBot.TClient.Commands;
using JOBot.TClient.Commands.Buttons;
using JOBot.TClient.Infrastructure.Attributes.Authorization;
using JOBot.TClient.Infrastructure.Extensions;
using JOBot.TClient.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -33,7 +35,8 @@ public sealed class BotBackgroundService(
{
//Commands
["/start"] = scope.ServiceProvider.GetRequiredService<StartCommand>(),
["/menu"] = scope.ServiceProvider.GetRequiredService<StartCommand>(),
["/menu"] = scope.ServiceProvider.GetRequiredService<MenuCommand>(),
["/info"] = scope.ServiceProvider.GetRequiredService<InfoCommand>(),
//Buttons
[ButtonResource.EULAAgrement] = scope.ServiceProvider.GetRequiredService<EulaAgreementButtonCommand>(),
@ -52,8 +55,16 @@ public sealed class BotBackgroundService(
if (commands.TryGetValue(text, out var command))
{
if (command is IAuthorizedTelegramCommand authorizedTelegramCommand)
{
var attribute = Attribute.GetCustomAttribute(command.GetType(), typeof(AcceptNotPreparedAttribute));
if (!user.IsPrepared() && attribute is not AcceptNotPreparedAttribute)
{
await commands["/start"].ExecuteAsync(update, ct); //заставляем пользователя завершить регистрацию
return;
}
await authorizedTelegramCommand.ExecuteAsync(update, user, ct);
else await command.ExecuteAsync(update, ct); //А если вызвать /start когда зареган? То-то и оно, но всё равно надо подумать
}
else await command.ExecuteAsync(update, ct);
return;
}

View File

@ -24,6 +24,8 @@ public static class DependencyInjection
#region Commands
services.AddScoped<StartCommand>();
services.AddScoped<MenuCommand>();
services.AddScoped<InfoCommand>();
//buttons
services.AddScoped<EulaAgreementButtonCommand>();

View File

@ -0,0 +1,4 @@
namespace JOBot.TClient.Infrastructure.Attributes.Authorization;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class AcceptNotPreparedAttribute : Attribute;

View File

@ -0,0 +1,9 @@
using JOBot.Proto;
namespace JOBot.TClient.Infrastructure.Extensions;
public static class GRpcModelsExtensions
{
public static bool IsPrepared(this GetUserResponse user) => user is { Eula: true, IsLogged: true } &&
!string.IsNullOrEmpty(user.CVUrl);
}

View File

@ -1,5 +1,3 @@
using Grpc.Core;
using JetBrains.Annotations;
using JOBot.Proto;
using JOBot.TClient.Infrastructure.Exceptions;
using Telegram.Bot;
@ -8,7 +6,6 @@ using User = JOBot.Proto.User;
namespace JOBot.TClient.Services;
[UsedImplicitly]
public class PrepareUserService(ITelegramBotClient bot, User.UserClient userClient) : UserService(bot, userClient)
{
private readonly ITelegramBotClient _bot = bot;

View File

@ -13,10 +13,8 @@ public class PrepareUserState(PrepareUserService prepareUserService, MenuService
/// <param name="ct">Cancellation token</param>
public async Task TryToPrepareUser(Update update, CancellationToken ct = default)
{
var user = await prepareUserService.GetUser(update, ct);
if (user == null)
user = await prepareUserService.RegisterUser(update, ct);
var user = await prepareUserService.GetUser(update, ct) ?? await prepareUserService.RegisterUser(update, ct);
if (!user.Eula)
{
await prepareUserService.AskForEulaAgreement(update, ct);
@ -31,12 +29,17 @@ public class PrepareUserState(PrepareUserService prepareUserService, MenuService
/// </summary>
/// <param name="update"></param>
/// <param name="ct"></param>
public async Task UserAcceptedEula(Update update, CancellationToken ct = default)
public async Task AcceptEula(Update update, CancellationToken ct = default)
{
await prepareUserService.AcceptEula(update, ct: ct);
await OnUserEulaValidStage(update, ct);
}
/// <summary>
/// Continue prepare stage
/// </summary>
/// <param name="update"></param>
/// <param name="ct"></param>
private async Task OnUserEulaValidStage(Update update, CancellationToken ct = default)
{
await menuService.RenderMenu(update, ct); //boilerplate

View File

@ -86,5 +86,14 @@ namespace JOBot.TClient {
return ResourceManager.GetString("FallbackMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Это бот для упрощения поиска работы на HH.ru.
/// </summary>
public static string Info {
get {
return ResourceManager.GetString("Info", resourceCulture);
}
}
}
}

View File

@ -28,4 +28,7 @@
<data name="CommandNotFound" xml:space="preserve">
<value>Команда не найдена, попробуйте что-то другое</value>
</data>
<data name="Info" xml:space="preserve">
<value>Это бот для упрощения поиска работы на HH.ru</value>
</data>
</root>