Files
GymLogAI/GymLogAI.Application/Handlers/ParseTelegramMessageHandler.cs
T
2026-04-19 13:12:04 +03:00

109 lines
4.2 KiB
C#

using GymLogAI.Application.Interfaces;
using GymLogAI.Core.Abstractions;
using GymLogAI.Core.Entities;
using GymLogAI.Core.Enums;
namespace GymLogAI.Application.Handlers;
public sealed class ParseTelegramMessageHandler(
ITelegramMessageRepository telegramMessageRepository,
IWorkoutRepository workoutRepository,
IExerciseRepository exerciseRepository,
IWorkoutParser workoutParser,
IEmbeddingService embeddingService,
IClock clock,
IIdGenerator idGenerator)
{
public async Task<bool> HandleAsync(Guid telegramMessageId, CancellationToken cancellationToken)
{
var message = await telegramMessageRepository.GetByIdAsync(telegramMessageId, cancellationToken);
if (message is null)
{
return false;
}
message.ParsingStatus = ParsingStatus.Processing;
message.ParsingError = null;
await telegramMessageRepository.UpdateAsync(message, cancellationToken);
try
{
var parsedWorkout = await workoutParser.ParseAsync(message.Text, cancellationToken);
if (parsedWorkout is null || parsedWorkout.Exercises.Count == 0)
{
message.ParsingStatus = ParsingStatus.Failed;
message.ParsingError = "Unable to parse workout from message.";
message.ParsedAtUtc = clock.UtcNow;
await telegramMessageRepository.UpdateAsync(message, cancellationToken);
return false;
}
var workout = new Workout
{
Id = idGenerator.New(),
UserId = message.UserId,
SourceTelegramMessageId = message.Id,
PerformedAtUtc = parsedWorkout.PerformedAtUtc,
Title = parsedWorkout.Title,
Notes = parsedWorkout.Notes,
SourceType = WorkoutSourceType.Telegram,
CreatedAtUtc = clock.UtcNow
};
foreach (var parsedExercise in parsedWorkout.Exercises.OrderBy(x => x.Order))
{
var exercise = await exerciseRepository.GetByNameAsync(parsedExercise.Name, cancellationToken)
?? await exerciseRepository.AddAsync(new Exercise
{
Id = idGenerator.New(),
Name = parsedExercise.Name.Trim(),
CreatedAtUtc = clock.UtcNow,
Embedding = await embeddingService.GenerateEmbeddingAsync(parsedExercise.Name, cancellationToken)
}, cancellationToken);
var workoutExercise = new WorkoutExercise
{
Id = idGenerator.New(),
WorkoutId = workout.Id,
ExerciseId = exercise.Id,
Order = parsedExercise.Order,
Notes = parsedExercise.Notes
};
foreach (var parsedSet in parsedExercise.Sets.OrderBy(x => x.Order))
{
workoutExercise.Sets.Add(new ExerciseSet
{
Id = idGenerator.New(),
WorkoutExerciseId = workoutExercise.Id,
Order = parsedSet.Order,
Repetitions = parsedSet.Repetitions,
WeightKg = parsedSet.WeightKg,
DurationSeconds = parsedSet.DurationSeconds,
DistanceMeters = parsedSet.DistanceMeters,
Notes = parsedSet.Notes
});
}
workout.WorkoutExercises.Add(workoutExercise);
}
await workoutRepository.AddAsync(workout, cancellationToken);
message.WorkoutId = workout.Id;
message.ParsingStatus = ParsingStatus.Parsed;
message.ParsedAtUtc = clock.UtcNow;
await telegramMessageRepository.UpdateAsync(message, cancellationToken);
return true;
}
catch (Exception ex)
{
message.ParsingStatus = ParsingStatus.Failed;
message.ParsingError = ex.Message;
message.ParsedAtUtc = clock.UtcNow;
await telegramMessageRepository.UpdateAsync(message, cancellationToken);
return false;
}
}
}