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); 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) => await FFmpegPathMustExist(dbContext); private static Task> FFmpegPathMustExist(TvContext dbContext) => dbContext.ConfigElements.GetValue(ConfigElementKey.FFmpegPath) .FilterT(File.Exists) .Map(maybePath => maybePath.ToValidation("FFmpeg path does not exist on filesystem")); }