Files
ersatztv/ErsatzTV.Core/Metadata/LocalFolderScanner.cs
T
Jason DoveandGitHub f392bab118 Database redesign (#31)
* starting database redesign

* set season and episode numbers

* use datetimes in db (utc); update movie metadata

* get movie cards from new table

* copy show/episode metadata

* remove old movie metadata type

* rename new movie metadata type

* code cleanup

* start to remove old television classes

* remove old television tables from database

* fix playout building

* fix collection views

* fix show/season views

* clean up movie metadata table

* fix scanner tests

* add libraries ui

* code cleanup

* fix movie scanning/metadata

* add library scan button to ui

* delete library path from ui

* temp disable movie scanning

* remove orphan media items and prevent duplicate paths

* attach artwork to metadata

* fix split show/season display

* fix television artwork

* store year distinct from release date

* fix collections ui

* code cleanup

* add library paths from ui

* fix adding to collections from ui

* fix schedule items loading

* schedule editing works again

* remove some todos

* more cleanup

* fix unit tests

* fix episode sorting

* fix deleting show library paths

* remove unused class

* fix playout list in ui

* fix log viewer

* start to use version/file instead of statistics

* clean up old columns

* fix playout display (time zone)

* fix playback

* fix channel guide time zone

* cascade more deletes

* fix compiler warnings

* fix adding new seasons

* use artwork for channel logo

* clean cache folder on startup (move channel logos, delete everything else)

* log database migration

* update homepage docs for libraries

* fix adding new channel with logo

* fix episode numbers in epg
2021-02-28 17:48:01 +00:00

138 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Images;
using ErsatzTV.Core.Interfaces.Metadata;
using LanguageExt;
using Microsoft.Extensions.Logging;
using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Metadata
{
public abstract class LocalFolderScanner
{
private static readonly SHA1CryptoServiceProvider Crypto;
public static readonly List<string> VideoFileExtensions = new()
{
".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".ogg", ".mp4",
".m4p", ".m4v", ".avi", ".wmv", ".mov", ".mkv", ".ts"
};
public static readonly List<string> ImageFileExtensions = new()
{
"jpg", "jpeg", "png", "gif", "tbn"
};
public static readonly List<string> ExtraFiles = new()
{
"behindthescenes", "deleted", "featurette",
"interview", "scene", "short", "trailer", "other"
};
public static readonly List<string> ExtraDirectories = new List<string>
{
"behind the scenes", "deleted scenes", "featurettes",
"interviews", "scenes", "shorts", "trailers", "other",
"extras", "specials"
}
.Map(s => $"{Path.DirectorySeparatorChar}{s}{Path.DirectorySeparatorChar}")
.ToList();
private readonly IImageCache _imageCache;
private readonly ILocalFileSystem _localFileSystem;
private readonly ILocalStatisticsProvider _localStatisticsProvider;
private readonly ILogger _logger;
static LocalFolderScanner() => Crypto = new SHA1CryptoServiceProvider();
protected LocalFolderScanner(
ILocalFileSystem localFileSystem,
ILocalStatisticsProvider localStatisticsProvider,
IImageCache imageCache,
ILogger logger)
{
_localFileSystem = localFileSystem;
_localStatisticsProvider = localStatisticsProvider;
_imageCache = imageCache;
_logger = logger;
}
protected async Task<Either<BaseError, T>> UpdateStatistics<T>(T mediaItem, string ffprobePath)
where T : MediaItem
{
try
{
MediaVersion version = mediaItem switch
{
Movie m => m.MediaVersions.Head(),
Episode e => e.MediaVersions.Head(),
_ => throw new ArgumentOutOfRangeException(nameof(mediaItem))
};
string path = version.MediaFiles.Head().Path;
if (version.DateUpdated < _localFileSystem.GetLastWriteTime(path))
{
_logger.LogDebug("Refreshing {Attribute} for {Path}", "Statistics", path);
await _localStatisticsProvider.RefreshStatistics(ffprobePath, mediaItem);
}
return mediaItem;
}
catch (Exception ex)
{
return BaseError.New(ex.Message);
}
}
protected bool RefreshArtwork(string artworkFile, Domain.Metadata metadata, ArtworkKind artworkKind)
{
DateTime lastWriteTime = _localFileSystem.GetLastWriteTime(artworkFile);
metadata.Artwork ??= new List<Artwork>();
Option<Artwork> maybePoster =
Optional(metadata.Artwork).Flatten().FirstOrDefault(a => a.ArtworkKind == artworkKind);
bool shouldRefresh = maybePoster.Match(
artwork => artwork.DateUpdated < lastWriteTime,
true);
if (shouldRefresh)
{
_logger.LogDebug("Refreshing {Attribute} from {Path}", artworkKind, artworkFile);
string cacheName = _imageCache.CopyArtworkToCache(artworkFile, artworkKind);
maybePoster.Match(
artwork =>
{
artwork.Path = cacheName;
artwork.DateUpdated = lastWriteTime;
},
() =>
{
var artwork = new Artwork
{
Path = cacheName,
DateAdded = DateTime.UtcNow,
DateUpdated = lastWriteTime,
ArtworkKind = artworkKind
};
metadata.Artwork.Add(artwork);
});
return true;
}
return false;
}
}
}