feat: added auth for telegram stage

This commit is contained in:
Pavel-Savely Savianok 2025-07-16 20:34:29 +03:00
parent bae7a0267d
commit fcdc4476df
9 changed files with 68 additions and 14 deletions

View File

@ -16,7 +16,7 @@ public class HeadHunterService(ILogger<HeadHunterService> logger, IOptions<HeadH
/// </summary> /// </summary>
/// <param name="userId">Telegram UserId</param> /// <param name="userId">Telegram UserId</param>
/// <returns>Link for auth</returns> /// <returns>Link for auth</returns>
public string GenerateAuthLink(int userId) public string GenerateAuthLink(long userId)
{ {
var redirectUri = new UriBuilder(_config.Links.HookDomain) var redirectUri = new UriBuilder(_config.Links.HookDomain)
{ {

View File

@ -1,3 +1,4 @@
using Google.Protobuf.WellKnownTypes;
using Grpc.Core; using Grpc.Core;
using JOBot.Backend.DAL.Context; using JOBot.Backend.DAL.Context;
using JOBot.Backend.DAL.Models; using JOBot.Backend.DAL.Models;
@ -7,7 +8,7 @@ using User = JOBot.Backend.DAL.Models.User;
namespace JOBot.Backend.Services.gRPC; namespace JOBot.Backend.Services.gRPC;
public class UserService(AppDbContext dbContext) : Proto.User.UserBase public class UserService(AppDbContext dbContext, HeadHunterService hhService) : Proto.User.UserBase
{ {
/// <summary> /// <summary>
/// Create user /// Create user
@ -62,6 +63,16 @@ public class UserService(AppDbContext dbContext) : Proto.User.UserBase
return new AcceptEulaResponse { Success = true }; return new AcceptEulaResponse { Success = true };
} }
public override Task<GetHeadHunterAuthHookResponse> GetHeadHunterAuthHook(
GetHeadHunterAuthHookRequest request,
ServerCallContext context)
{
return Task.Run(() => new GetHeadHunterAuthHookResponse
{
RegistrationUrl = hhService.GenerateAuthLink(request.UserId)
});
}
/// <summary> /// <summary>
/// Throw RPCException if user not found /// Throw RPCException if user not found
/// </summary> /// </summary>

View File

@ -12,6 +12,7 @@ public class EulaAgreementButtonCommand(PrepareUserState prepareUserState) : IAu
{ {
public async Task ExecuteAsync(Update update, GetUserResponse user, CancellationToken ct) public async Task ExecuteAsync(Update update, GetUserResponse user, CancellationToken ct)
{ {
await prepareUserState.AcceptEula(update, ct); if (!user.Eula)
await prepareUserState.AcceptEula(user, update, ct);
} }
} }

View File

@ -6,12 +6,10 @@ namespace JOBot.TClient.Services;
public class MenuService(ITelegramBotClient bot) public class MenuService(ITelegramBotClient bot)
{ {
public Task RenderMenu(Update update, CancellationToken ct = default) public async Task RenderMenu(Update update, CancellationToken ct = default)
{ {
ArgumentNullException.ThrowIfNull(update.Message?.From); ArgumentNullException.ThrowIfNull(update.Message?.From);
bot.SendMessage(update.Message.From.Id,"PrepareUser stage is done.", cancellationToken: ct); await bot.SendMessage(update.Message.From.Id,"PrepareUser stage is done.", cancellationToken: ct);
return Task.CompletedTask;
} }
} }

View File

@ -83,4 +83,19 @@ public class PrepareUserService(ITelegramBotClient bot, User.UserClient userClie
if (!result.Success) if (!result.Success)
throw new FallbackException(TextResource.FallbackMessage, update.Message, _bot); throw new FallbackException(TextResource.FallbackMessage, update.Message, _bot);
} }
public async Task Auth(Update update, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(update.Message?.From);
var url = await _userClient.GetHeadHunterAuthHookAsync(new GetHeadHunterAuthHookRequest()
{
UserId = update.Message.From.Id
});
await _bot.SendMessage(
update.Message.From.Id,
string.Format(TextResource.AskForAuth, [url]),
cancellationToken: ct);
}
} }

View File

@ -1,3 +1,4 @@
using JOBot.Proto;
using JOBot.TClient.Services; using JOBot.TClient.Services;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using User = JOBot.Proto.User; using User = JOBot.Proto.User;
@ -21,27 +22,33 @@ public class PrepareUserState(PrepareUserService prepareUserService, MenuService
return; //interrupt while eula isn't accepted return; //interrupt while eula isn't accepted
} }
await OnUserEulaValidStage(update, ct); await OnUserEulaValidStage(user, update, ct);
} }
/// <summary> /// <summary>
/// Signal for accepted eula /// Signal for accepted eula
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="update"></param> /// <param name="update"></param>
/// <param name="ct"></param> /// <param name="ct"></param>
public async Task AcceptEula(Update update, CancellationToken ct = default) public async Task AcceptEula(GetUserResponse user, Update update, CancellationToken ct = default)
{ {
await prepareUserService.AcceptEula(update, ct: ct); await prepareUserService.AcceptEula(update, ct: ct);
await OnUserEulaValidStage(update, ct); await OnUserEulaValidStage(user, update, ct);
} }
/// <summary> /// <summary>
/// Continue prepare stage /// Continue prepare stage
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="update"></param> /// <param name="update"></param>
/// <param name="ct"></param> /// <param name="ct"></param>
private async Task OnUserEulaValidStage(Update update, CancellationToken ct = default) private async Task OnUserEulaValidStage(GetUserResponse user, Update update, CancellationToken ct = default)
{ {
if (!user.IsLogged)
{
prepareUserService.Auth(update, ct);
}
await menuService.RenderMenu(update, ct); //boilerplate await menuService.RenderMenu(update, ct); //boilerplate
} }
} }

View File

@ -59,6 +59,15 @@ namespace JOBot.TClient {
} }
} }
/// <summary>
/// Looks up a localized string similar to Авторизируйтесь на сайте HeadHunter для получения доступа к резюме и вакансиям {0}.
/// </summary>
public static string AskForAuth {
get {
return ResourceManager.GetString("AskForAuth", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Команда не найдена, попробуйте что-то другое. /// Looks up a localized string similar to Команда не найдена, попробуйте что-то другое.
/// </summary> /// </summary>

View File

@ -34,4 +34,7 @@ https://hh.ru/account/agreement?backurl=%2Faccount%2Fsignup%3Fbackurl%3D%252F%26
<data name="Info" xml:space="preserve"> <data name="Info" xml:space="preserve">
<value>Это бот для упрощения поиска работы на HH.ru</value> <value>Это бот для упрощения поиска работы на HH.ru</value>
</data> </data>
<data name="AskForAuth" xml:space="preserve">
<value>Авторизируйтесь на сайте HeadHunter для получения доступа к резюме и вакансиям {0}</value>
</data>
</root> </root>

View File

@ -1,14 +1,16 @@
syntax = "proto3"; syntax = "proto3";
option csharp_namespace = "JOBot.Proto"; option csharp_namespace = "JOBot.Proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/empty.proto";
service User { service User {
rpc Register (RegisterRequest) returns (RegisterResponse); rpc Register (RegisterRequest) returns (RegisterResponse);
rpc GetUser (GetUserRequest) returns (GetUserResponse); rpc GetUser (GetUserRequest) returns (GetUserResponse);
rpc AcceptEula (AcceptEulaRequest) returns (AcceptEulaResponse); rpc AcceptEula (AcceptEulaRequest) returns (AcceptEulaResponse);
rpc GetHeadHunterAuthHook(GetHeadHunterAuthHookRequest) returns (GetHeadHunterAuthHookResponse);
} }
import "google/protobuf/wrappers.proto";
message RegisterRequest{ message RegisterRequest{
int64 user_id = 1; int64 user_id = 1;
google.protobuf.StringValue username = 2; google.protobuf.StringValue username = 2;
@ -38,3 +40,11 @@ message AcceptEulaRequest {
message AcceptEulaResponse{ message AcceptEulaResponse{
bool success = 1; bool success = 1;
} }
message GetHeadHunterAuthHookRequest{
int64 user_id = 1;
}
message GetHeadHunterAuthHookResponse{
string registration_url = 1;
}