using CliWrap; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.Streaming; public class GetSeekTextSubtitleProcessHandler( IDbContextFactory dbContextFactory, IFFmpegProcessService ffmpegProcessService) : IRequestHandler> { public async Task> Handle( GetSeekTextSubtitleProcess request, CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, cancellationToken); return await validation.Match( ffmpegPath => GetProcess(request, ffmpegPath, cancellationToken), error => Task.FromResult>(error.Join())); } private async Task> GetProcess( GetSeekTextSubtitleProcess request, string ffmpegPath, CancellationToken cancellationToken) { Command process = await ffmpegProcessService.SeekTextSubtitle( ffmpegPath, request.PathAndCodec.Path, request.PathAndCodec.Codec, request.Seek, cancellationToken); return new SeekTextSubtitleProcess(process); } private static async Task> Validate( TvContext dbContext, CancellationToken cancellationToken) => await FFmpegPathMustExist(dbContext, cancellationToken); private static Task> FFmpegPathMustExist( TvContext dbContext, CancellationToken cancellationToken) => dbContext.ConfigElements.GetValue(ConfigElementKey.FFmpegPath, cancellationToken) .FilterT(File.Exists) .Map(maybePath => maybePath.ToValidation("FFmpeg path does not exist on filesystem")); }