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), error => Task.FromResult>(error.Join())); } private async Task> GetProcess( GetSeekTextSubtitleProcess request, string ffmpegPath) { Command process = await ffmpegProcessService.SeekTextSubtitle( ffmpegPath, request.SubtitlePath, request.Seek); 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")); }