Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 lines
3.8 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ErsatzTV.Core.Domain;
using LanguageExt;
using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Metadata
{
public class TestMediaScanner
{
// @formatter:off
private static readonly Seq<string> VideoFileExtensions = Seq(
".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".ogg", ".mp4",
".m4p", ".m4v", ".avi", ".wmv", ".mov", ".mkv", ".ts");
// @formatter:on
private static readonly Seq<string> ImageFileExtensions = Seq("jpg", "jpeg", "png", "gif", "tbn");
public Seq<LocalMediaItemScanningPlan> DetermineActions(
MediaType mediaType,
Seq<MediaItem> mediaItems,
Seq<string> files)
{
var results = new IntermediateResults();
var videoFiles = files.Filter(f => VideoFileExtensions.Contains(Path.GetExtension(f)));
(Seq<string> newFiles, Seq<MediaItem> existingMediaItems) = videoFiles.Map(
s => mediaItems.Find(i => i.Path == s).ToEither(s))
.Partition();
// new files
foreach (string file in newFiles)
{
results.Add(file, new ItemScanningPlan(file, ScanningAction.Statistics));
Option<string> maybeNfoFile = LocateNfoFile(mediaType, files, file);
maybeNfoFile.BiIter(
nfoFile => results.Add(file, new ItemScanningPlan(nfoFile, ScanningAction.SidecarMetadata)),
() => results.Add(file, new ItemScanningPlan(file, ScanningAction.FallbackMetadata)));
Option<string> maybePoster = LocatePoster(mediaType, files, file);
maybePoster.IfSome(
posterFile => results.Add(file, new ItemScanningPlan(posterFile, ScanningAction.Poster)));
}
// existing media items
return results.Summarize();
}
private static Option<string> LocateNfoFile(MediaType mediaType, Seq<string> files, string file)
{
switch (mediaType)
{
case MediaType.Movie:
string movieAsNfo = Path.ChangeExtension(file, "nfo");
string movieNfo = Path.Combine(Path.GetDirectoryName(file) ?? string.Empty, "movie.nfo");
return Seq(movieAsNfo, movieNfo)
.Filter(s => files.Contains(s))
.HeadOrNone();
}
return None;
}
private static Option<string> LocatePoster(MediaType mediaType, Seq<string> files, string file)
{
string folder = Path.GetDirectoryName(file) ?? string.Empty;
switch (mediaType)
{
case MediaType.Movie:
IEnumerable<string> possiblePosters = ImageFileExtensions.Collect(
ext => new[] { $"poster.{ext}", Path.GetFileNameWithoutExtension(file) + $"-poster.{ext}" })
.Map(f => Path.Combine(folder, f));
return possiblePosters.Filter(s => files.Contains(s)).HeadOrNone();
}
return None;
}
private class IntermediateResults
{
private readonly List<Tuple<Either<string, MediaItem>, ItemScanningPlan>> _rawResults = new();
public void Add(Either<string, MediaItem> source, ItemScanningPlan plan) =>
_rawResults.Add(Tuple(source, plan));
public Seq<LocalMediaItemScanningPlan> Summarize() =>
_rawResults
.GroupBy(t => t.Item1)
.Select(g => new LocalMediaItemScanningPlan(g.Key, g.Select(g2 => g2.Item2).ToList()))
.ToSeq();
}
}
}