using System.IO; 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; namespace ErsatzTV.Application.MediaSources.Commands { public class ScanLocalMediaSourceHandler : IRequestHandler> { private readonly IConfigElementRepository _configElementRepository; private readonly ILocalMediaScanner _localMediaScanner; private readonly IMediaSourceRepository _mediaSourceRepository; public ScanLocalMediaSourceHandler( IMediaSourceRepository mediaSourceRepository, IConfigElementRepository configElementRepository, ILocalMediaScanner localMediaScanner) { _mediaSourceRepository = mediaSourceRepository; _configElementRepository = configElementRepository; _localMediaScanner = localMediaScanner; } public Task> Handle(ScanLocalMediaSource request, CancellationToken cancellationToken) => Validate(request) .MapT( p => _localMediaScanner.ScanLocalMediaSource(p.LocalMediaSource, p.FFprobePath) .Map(_ => p.LocalMediaSource.Name)) .Bind(v => v.ToEitherAsync()); private async Task> Validate(ScanLocalMediaSource request) => (await LocalMediaSourceMustExist(request), await ValidateFFprobePath()) .Apply((localMediaSource, ffprobePath) => new RequestParameters(localMediaSource, ffprobePath)); private Task> LocalMediaSourceMustExist( ScanLocalMediaSource request) => _mediaSourceRepository.Get(request.MediaSourceId) .Map(maybeMediaSource => maybeMediaSource.Map(ms => ms as LocalMediaSource)) .Map(v => v.ToValidation($"Local media source {request.MediaSourceId} does not exist.")); private Task> ValidateFFprobePath() => _configElementRepository.GetValue(ConfigElementKey.FFprobePath) .FilterT(File.Exists) .Map( ffprobePath => ffprobePath.ToValidation("FFprobe path does not exist on the file system")); private record RequestParameters(LocalMediaSource LocalMediaSource, string FFprobePath); } }