109 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|