using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Images; using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; using Microsoft.Extensions.Logging; using static LanguageExt.Prelude; namespace ErsatzTV.Core.Metadata { public class LocalPosterProvider : ILocalPosterProvider { private static readonly string[] SupportedExtensions = { "jpg", "jpeg", "png", "gif", "tbn" }; private readonly IImageCache _imageCache; private readonly ILogger _logger; private readonly IMediaItemRepository _mediaItemRepository; public LocalPosterProvider( IMediaItemRepository mediaItemRepository, IImageCache imageCache, ILogger logger) { _mediaItemRepository = mediaItemRepository; _imageCache = imageCache; _logger = logger; } public async Task RefreshPoster(MediaItem mediaItem) { Option maybePosterPath = mediaItem switch { MovieMediaItem m => RefreshMoviePoster(m), TelevisionEpisodeMediaItem e => RefreshTelevisionPoster(e), _ => None }; await maybePosterPath.Match( path => SavePosterToDisk(mediaItem, path), Task.CompletedTask); } public async Task SavePosterToDisk(MediaItem mediaItem, string posterPath) { byte[] originalBytes = await File.ReadAllBytesAsync(posterPath); Either maybeHash = await _imageCache.ResizeAndSaveImage(originalBytes, 220, null); await maybeHash.Match( hash => { mediaItem.Poster = hash; return _mediaItemRepository.Update(mediaItem); }, error => { _logger.LogWarning("Unable to save poster to disk from {Path}: {Error}", posterPath, error.Value); return Task.CompletedTask; }); } private static Option RefreshMoviePoster(MediaItem mediaItem) { string folder = Path.GetDirectoryName(mediaItem.Path); if (folder != null) { IEnumerable possiblePaths = SupportedExtensions.Collect( e => new[] { $"poster.{e}", Path.GetFileNameWithoutExtension(mediaItem.Path) + $"-poster.{e}" }); Option maybePoster = possiblePaths.Map(p => Path.Combine(folder, p)).FirstOrDefault(File.Exists); return maybePoster; } return None; } private Option RefreshTelevisionPoster(MediaItem mediaItem) { string folder = Directory.GetParent(Path.GetDirectoryName(mediaItem.Path) ?? string.Empty)?.FullName; if (folder != null) { IEnumerable possiblePaths = SupportedExtensions.Collect(e => new[] { $"poster.{e}" }); Option maybePoster = possiblePaths.Map(p => Path.Combine(folder, p)).FirstOrDefault(File.Exists); return maybePoster; } return None; } } }