Files
ersatztv/ErsatzTV.Core/Metadata/LocalPosterProvider.cs
T
Jason DoveandGitHub 8fb23f2edb rewrite local media scanner (#25)
* spike new scanner

* add existing items to new scanner

* add collection refresh actions

* add tv show metadata and posters

* update metadata and posters when nfo/poster files are updated

* add "remove" action, test for all supported file extensions

* update statistics when primary video file is updated

* reflect that collections are "sourced" from nfo

* implement most scanning actions

* cleanup

* fix startup

* cross-platform scanner tests
2021-02-15 23:55:19 +00:00

94 lines
3.4 KiB
C#

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<LocalPosterProvider> _logger;
private readonly IMediaItemRepository _mediaItemRepository;
public LocalPosterProvider(
IMediaItemRepository mediaItemRepository,
IImageCache imageCache,
ILogger<LocalPosterProvider> logger)
{
_mediaItemRepository = mediaItemRepository;
_imageCache = imageCache;
_logger = logger;
}
public async Task RefreshPoster(MediaItem mediaItem)
{
Option<string> maybePosterPath = mediaItem.Metadata.MediaType switch
{
MediaType.Movie => RefreshMoviePoster(mediaItem),
MediaType.TvShow => RefreshTelevisionPoster(mediaItem),
_ => None
};
await maybePosterPath.Match(
path => SavePosterToDisk(mediaItem, path),
Task.CompletedTask);
}
private static Option<string> RefreshMoviePoster(MediaItem mediaItem)
{
string folder = Path.GetDirectoryName(mediaItem.Path);
if (folder != null)
{
IEnumerable<string> possiblePaths = SupportedExtensions.Collect(
e => new[] { $"poster.{e}", Path.GetFileNameWithoutExtension(mediaItem.Path) + $"-poster.{e}" });
Option<string> maybePoster =
possiblePaths.Map(p => Path.Combine(folder, p)).FirstOrDefault(File.Exists);
return maybePoster;
}
return None;
}
private Option<string> RefreshTelevisionPoster(MediaItem mediaItem)
{
string folder = Directory.GetParent(Path.GetDirectoryName(mediaItem.Path) ?? string.Empty)?.FullName;
if (folder != null)
{
IEnumerable<string> possiblePaths = SupportedExtensions.Collect(e => new[] { $"poster.{e}" });
Option<string> maybePoster =
possiblePaths.Map(p => Path.Combine(folder, p)).FirstOrDefault(File.Exists);
return maybePoster;
}
return None;
}
public async Task SavePosterToDisk(MediaItem mediaItem, string posterPath)
{
byte[] originalBytes = await File.ReadAllBytesAsync(posterPath);
Either<BaseError, string> 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;
});
}
}
}