Browse Source

improve ffmpeg/ffprobe path validation

pull/63/head
Jason Dove 5 years ago
parent
commit
0ee6e696a2
  1. 5
      ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettings.cs
  2. 67
      ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs
  3. 15
      ErsatzTV/Pages/FFmpeg.razor

5
ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettings.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
using MediatR;
using ErsatzTV.Core;
using LanguageExt;
namespace ErsatzTV.Application.FFmpegProfiles.Commands
{
public record UpdateFFmpegSettings(FFmpegSettingsViewModel Settings) : IRequest;
public record UpdateFFmpegSettings(FFmpegSettingsViewModel Settings) : MediatR.IRequest<Either<BaseError, Unit>>;
}

67
ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegSettingsHandler.cs

@ -1,21 +1,74 @@ @@ -1,21 +1,74 @@
using System.Threading;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using MediatR;
using Unit = MediatR.Unit;
namespace ErsatzTV.Application.FFmpegProfiles.Commands
{
public class UpdateFFmpegSettingsHandler : IRequestHandler<UpdateFFmpegSettings>
public class UpdateFFmpegSettingsHandler : MediatR.IRequestHandler<UpdateFFmpegSettings, Either<BaseError, Unit>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly ILocalFileSystem _localFileSystem;
public UpdateFFmpegSettingsHandler(IConfigElementRepository configElementRepository) =>
public UpdateFFmpegSettingsHandler(
IConfigElementRepository configElementRepository,
ILocalFileSystem localFileSystem)
{
_configElementRepository = configElementRepository;
_localFileSystem = localFileSystem;
}
public Task<Either<BaseError, Unit>> Handle(
UpdateFFmpegSettings request,
CancellationToken cancellationToken) =>
Validate(request)
.MapT(_ => ApplyUpdate(request))
.Bind(v => v.ToEitherAsync());
private async Task<Validation<BaseError, Unit>> Validate(UpdateFFmpegSettings request) =>
(await FFmpegMustExist(request), await FFprobeMustExist(request))
.Apply((_, _) => Unit.Default);
private Task<Validation<BaseError, Unit>> FFmpegMustExist(UpdateFFmpegSettings request) =>
ValidateToolPath(request.Settings.FFmpegPath, "ffmpeg");
private Task<Validation<BaseError, Unit>> FFprobeMustExist(UpdateFFmpegSettings request) =>
ValidateToolPath(request.Settings.FFprobePath, "ffprobe");
private async Task<Validation<BaseError, Unit>> ValidateToolPath(string path, string name)
{
if (!_localFileSystem.FileExists(path))
{
return BaseError.New($"{name} path does not exist");
}
var startInfo = new ProcessStartInfo
{
FileName = path,
Arguments = "-version",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
var test = new Process
{
StartInfo = startInfo
};
test.Start();
string output = await test.StandardOutput.ReadToEndAsync();
await test.WaitForExitAsync();
return test.ExitCode == 0 && output.Contains($"{name} version")
? Unit.Default
: BaseError.New($"Unable to verify {name} version");
}
public async Task<Unit> Handle(UpdateFFmpegSettings request, CancellationToken cancellationToken)
private async Task<Unit> ApplyUpdate(UpdateFFmpegSettings request)
{
Option<ConfigElement> ffmpegPath = await _configElementRepository.Get(ConfigElementKey.FFmpegPath);
Option<ConfigElement> ffprobePath = await _configElementRepository.Get(ConfigElementKey.FFprobePath);
@ -64,7 +117,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands @@ -64,7 +117,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands
_configElementRepository.Add(ce);
});
return Unit.Value;
return Unit.Default;
}
}
}

15
ErsatzTV/Pages/FFmpeg.razor

@ -2,8 +2,11 @@ @@ -2,8 +2,11 @@
@using ErsatzTV.Application.FFmpegProfiles
@using ErsatzTV.Application.FFmpegProfiles.Commands
@using ErsatzTV.Application.FFmpegProfiles.Queries
@using Unit = LanguageExt.Unit
@inject IDialogService Dialog
@inject IMediator Mediator
@inject ILogger<FFmpeg> Logger
@inject ISnackbar Snackbar
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
<MudCard>
@ -110,7 +113,17 @@ @@ -110,7 +113,17 @@
await LoadFFmpegProfilesAsync();
}
private Task SaveSettings() => Mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings));
private async Task SaveSettings()
{
Either<BaseError, Unit> result = await Mediator.Send(new UpdateFFmpegSettings(_ffmpegSettings));
result.Match(
Left: error =>
{
Snackbar.Add(error.Value, Severity.Error);
Logger.LogError("Unexpected error saving FFmpeg settings: {Error}", error.Value);
},
Right: _ => Snackbar.Add("Successfully saved FFmpeg settings", Severity.Success));
}
private static string ValidatePathExists(string path) => !File.Exists(path) ? "Path does not exist" : null;

Loading…
Cancel
Save