add fallback metadata for music videos (#134)
This commit is contained in:
@@ -8,6 +8,7 @@ namespace ErsatzTV.Core.Interfaces.Metadata
|
|||||||
ShowMetadata GetFallbackMetadataForShow(string showFolder);
|
ShowMetadata GetFallbackMetadataForShow(string showFolder);
|
||||||
Tuple<EpisodeMetadata, int> GetFallbackMetadata(Episode episode);
|
Tuple<EpisodeMetadata, int> GetFallbackMetadata(Episode episode);
|
||||||
MovieMetadata GetFallbackMetadata(Movie movie);
|
MovieMetadata GetFallbackMetadata(Movie movie);
|
||||||
|
MusicVideoMetadata GetFallbackMetadata(MusicVideo musicVideo);
|
||||||
string GetSortTitle(string title);
|
string GetSortTitle(string title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ErsatzTV.Core.Domain;
|
using ErsatzTV.Core.Domain;
|
||||||
using LanguageExt;
|
|
||||||
|
|
||||||
namespace ErsatzTV.Core.Interfaces.Metadata
|
namespace ErsatzTV.Core.Interfaces.Metadata
|
||||||
{
|
{
|
||||||
public interface ILocalMetadataProvider
|
public interface ILocalMetadataProvider
|
||||||
{
|
{
|
||||||
Task<ShowMetadata> GetMetadataForShow(string showFolder);
|
Task<ShowMetadata> GetMetadataForShow(string showFolder);
|
||||||
Task<Option<MusicVideoMetadata>> GetMetadataForMusicVideo(string filePath);
|
|
||||||
Task<bool> RefreshSidecarMetadata(Movie movie, string nfoFileName);
|
Task<bool> RefreshSidecarMetadata(Movie movie, string nfoFileName);
|
||||||
Task<bool> RefreshSidecarMetadata(Show televisionShow, string nfoFileName);
|
Task<bool> RefreshSidecarMetadata(Show televisionShow, string nfoFileName);
|
||||||
Task<bool> RefreshSidecarMetadata(Episode episode, string nfoFileName);
|
Task<bool> RefreshSidecarMetadata(Episode episode, string nfoFileName);
|
||||||
Task<bool> RefreshSidecarMetadata(MusicVideo musicVideo, string nfoFileName);
|
Task<bool> RefreshSidecarMetadata(MusicVideo musicVideo, string nfoFileName);
|
||||||
Task<bool> RefreshFallbackMetadata(Movie movie);
|
Task<bool> RefreshFallbackMetadata(Movie movie);
|
||||||
Task<bool> RefreshFallbackMetadata(Episode episode);
|
Task<bool> RefreshFallbackMetadata(Episode episode);
|
||||||
|
Task<bool> RefreshFallbackMetadata(MusicVideo musicVideo);
|
||||||
Task<bool> RefreshFallbackMetadata(Show televisionShow, string showFolder);
|
Task<bool> RefreshFallbackMetadata(Show televisionShow, string showFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories
|
|||||||
{
|
{
|
||||||
public interface IMusicVideoRepository
|
public interface IMusicVideoRepository
|
||||||
{
|
{
|
||||||
Task<Option<MusicVideo>> GetByMetadata(LibraryPath libraryPath, MusicVideoMetadata metadata);
|
Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> GetOrAdd(LibraryPath libraryPath, string path);
|
||||||
|
|
||||||
Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> Add(
|
|
||||||
LibraryPath libraryPath,
|
|
||||||
string filePath,
|
|
||||||
MusicVideoMetadata metadata);
|
|
||||||
|
|
||||||
Task<IEnumerable<string>> FindMusicVideoPaths(LibraryPath libraryPath);
|
Task<IEnumerable<string>> FindMusicVideoPaths(LibraryPath libraryPath);
|
||||||
Task<List<int>> DeleteByPath(LibraryPath libraryPath, string path);
|
Task<List<int>> DeleteByPath(LibraryPath libraryPath, string path);
|
||||||
Task<bool> AddGenre(MusicVideoMetadata metadata, Genre genre);
|
Task<bool> AddGenre(MusicVideoMetadata metadata, Genre genre);
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
return fileName != null ? GetMovieMetadata(fileName, metadata) : metadata;
|
return fileName != null ? GetMovieMetadata(fileName, metadata) : metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MusicVideoMetadata GetFallbackMetadata(MusicVideo musicVideo)
|
||||||
|
{
|
||||||
|
string path = musicVideo.MediaVersions.Head().MediaFiles.Head().Path;
|
||||||
|
string fileName = Path.GetFileName(path);
|
||||||
|
var metadata = new MusicVideoMetadata
|
||||||
|
{
|
||||||
|
MetadataKind = MetadataKind.Fallback,
|
||||||
|
Title = fileName ?? path
|
||||||
|
};
|
||||||
|
|
||||||
|
return fileName != null ? GetMusicVideoMetadata(fileName, metadata) : metadata;
|
||||||
|
}
|
||||||
|
|
||||||
public string GetSortTitle(string title)
|
public string GetSortTitle(string title)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(title))
|
if (string.IsNullOrWhiteSpace(title))
|
||||||
@@ -112,6 +125,30 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MusicVideoMetadata GetMusicVideoMetadata(string fileName, MusicVideoMetadata metadata)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const string PATTERN = @"^(.*?) - (.*?).\w+$";
|
||||||
|
Match match = Regex.Match(fileName, PATTERN);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
metadata.Artist = match.Groups[1].Value;
|
||||||
|
metadata.Title = match.Groups[2].Value;
|
||||||
|
metadata.Genres = new List<Genre>();
|
||||||
|
metadata.Tags = new List<Tag>();
|
||||||
|
metadata.Studios = new List<Studio>();
|
||||||
|
metadata.DateUpdated = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
private ShowMetadata GetTelevisionShowMetadata(string fileName, ShowMetadata metadata)
|
private ShowMetadata GetTelevisionShowMetadata(string fileName, ShowMetadata metadata)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -70,23 +70,6 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Option<MusicVideoMetadata>> GetMetadataForMusicVideo(string filePath)
|
|
||||||
{
|
|
||||||
string nfoFileName = Path.ChangeExtension(filePath, "nfo");
|
|
||||||
Option<MusicVideoMetadata> maybeMetadata = None;
|
|
||||||
if (_localFileSystem.FileExists(nfoFileName))
|
|
||||||
{
|
|
||||||
maybeMetadata = await LoadMusicVideoMetadata(nfoFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return maybeMetadata.Map(
|
|
||||||
metadata =>
|
|
||||||
{
|
|
||||||
metadata.SortTitle = _fallbackMetadataProvider.GetSortTitle(metadata.Title);
|
|
||||||
return metadata;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> RefreshSidecarMetadata(Movie movie, string nfoFileName) =>
|
public Task<bool> RefreshSidecarMetadata(Movie movie, string nfoFileName) =>
|
||||||
LoadMovieMetadata(movie, nfoFileName).Bind(
|
LoadMovieMetadata(movie, nfoFileName).Bind(
|
||||||
maybeMetadata => maybeMetadata.Match(
|
maybeMetadata => maybeMetadata.Match(
|
||||||
@@ -109,7 +92,7 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
LoadMusicVideoMetadata(nfoFileName).Bind(
|
LoadMusicVideoMetadata(nfoFileName).Bind(
|
||||||
maybeMetadata => maybeMetadata.Match(
|
maybeMetadata => maybeMetadata.Match(
|
||||||
metadata => ApplyMetadataUpdate(musicVideo, metadata),
|
metadata => ApplyMetadataUpdate(musicVideo, metadata),
|
||||||
() => Task.FromResult(false)));
|
() => RefreshFallbackMetadata(musicVideo)));
|
||||||
|
|
||||||
public Task<bool> RefreshFallbackMetadata(Movie movie) =>
|
public Task<bool> RefreshFallbackMetadata(Movie movie) =>
|
||||||
ApplyMetadataUpdate(movie, _fallbackMetadataProvider.GetFallbackMetadata(movie));
|
ApplyMetadataUpdate(movie, _fallbackMetadataProvider.GetFallbackMetadata(movie));
|
||||||
@@ -117,6 +100,9 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
public Task<bool> RefreshFallbackMetadata(Episode episode) =>
|
public Task<bool> RefreshFallbackMetadata(Episode episode) =>
|
||||||
ApplyMetadataUpdate(episode, _fallbackMetadataProvider.GetFallbackMetadata(episode));
|
ApplyMetadataUpdate(episode, _fallbackMetadataProvider.GetFallbackMetadata(episode));
|
||||||
|
|
||||||
|
public Task<bool> RefreshFallbackMetadata(MusicVideo musicVideo) =>
|
||||||
|
ApplyMetadataUpdate(musicVideo, _fallbackMetadataProvider.GetFallbackMetadata(musicVideo));
|
||||||
|
|
||||||
public Task<bool> RefreshFallbackMetadata(Show televisionShow, string showFolder) =>
|
public Task<bool> RefreshFallbackMetadata(Show televisionShow, string showFolder) =>
|
||||||
ApplyMetadataUpdate(televisionShow, _fallbackMetadataProvider.GetFallbackMetadataForShow(showFolder));
|
ApplyMetadataUpdate(televisionShow, _fallbackMetadataProvider.GetFallbackMetadataForShow(showFolder));
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,7 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
var foldersCompleted = 0;
|
var foldersCompleted = 0;
|
||||||
|
|
||||||
var folderQueue = new Queue<string>();
|
var folderQueue = new Queue<string>();
|
||||||
foreach (string folder in _localFileSystem.ListSubdirectories(libraryPath.Path).OrderBy(identity))
|
folderQueue.Enqueue(libraryPath.Path);
|
||||||
{
|
|
||||||
folderQueue.Enqueue(folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (folderQueue.Count > 0)
|
while (folderQueue.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -83,20 +80,13 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
|
|
||||||
var allFiles = _localFileSystem.ListFiles(musicVideoFolder)
|
var allFiles = _localFileSystem.ListFiles(musicVideoFolder)
|
||||||
.Filter(f => VideoFileExtensions.Contains(Path.GetExtension(f)))
|
.Filter(f => VideoFileExtensions.Contains(Path.GetExtension(f)))
|
||||||
.Filter(
|
.Filter(f => f.Contains(" - "))
|
||||||
f => !ExtraFiles.Any(
|
|
||||||
e => Path.GetFileNameWithoutExtension(f).EndsWith(e, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (allFiles.Count == 0)
|
foreach (string subdirectory in _localFileSystem.ListSubdirectories(musicVideoFolder)
|
||||||
|
.OrderBy(identity))
|
||||||
{
|
{
|
||||||
foreach (string subdirectory in _localFileSystem.ListSubdirectories(musicVideoFolder)
|
folderQueue.Enqueue(subdirectory);
|
||||||
.OrderBy(identity))
|
|
||||||
{
|
|
||||||
folderQueue.Enqueue(subdirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_localFileSystem.GetLastWriteTime(musicVideoFolder) < lastScan)
|
if (_localFileSystem.GetLastWriteTime(musicVideoFolder) < lastScan)
|
||||||
@@ -107,11 +97,11 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
foreach (string file in allFiles.OrderBy(identity))
|
foreach (string file in allFiles.OrderBy(identity))
|
||||||
{
|
{
|
||||||
// TODO: figure out how to rebuild playouts
|
// TODO: figure out how to rebuild playouts
|
||||||
Either<BaseError, MediaItemScanResult<MusicVideo>> maybeMusicVideo =
|
Either<BaseError, MediaItemScanResult<MusicVideo>> maybeMusicVideo = await _musicVideoRepository
|
||||||
await FindOrCreateMusicVideo(libraryPath, file)
|
.GetOrAdd(libraryPath, file)
|
||||||
.BindT(musicVideo => UpdateStatistics(musicVideo, ffprobePath))
|
.BindT(musicVideo => UpdateStatistics(musicVideo, ffprobePath))
|
||||||
.BindT(UpdateMetadata)
|
.BindT(UpdateMetadata)
|
||||||
.BindT(UpdateThumbnail);
|
.BindT(UpdateThumbnail);
|
||||||
|
|
||||||
await maybeMusicVideo.Match(
|
await maybeMusicVideo.Match(
|
||||||
async result =>
|
async result =>
|
||||||
@@ -146,34 +136,13 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> FindOrCreateMusicVideo(
|
|
||||||
LibraryPath libraryPath,
|
|
||||||
string filePath)
|
|
||||||
{
|
|
||||||
Option<MusicVideoMetadata> maybeMetadata = await _localMetadataProvider.GetMetadataForMusicVideo(filePath);
|
|
||||||
return await maybeMetadata.Match(
|
|
||||||
async metadata =>
|
|
||||||
{
|
|
||||||
Option<MusicVideo> maybeMusicVideo =
|
|
||||||
await _musicVideoRepository.GetByMetadata(libraryPath, metadata);
|
|
||||||
return await maybeMusicVideo.Match(
|
|
||||||
musicVideo =>
|
|
||||||
Right<BaseError, MediaItemScanResult<MusicVideo>>(
|
|
||||||
new MediaItemScanResult<MusicVideo>(musicVideo))
|
|
||||||
.AsTask(),
|
|
||||||
async () => await _musicVideoRepository.Add(libraryPath, filePath, metadata));
|
|
||||||
},
|
|
||||||
() => Left<BaseError, MediaItemScanResult<MusicVideo>>(
|
|
||||||
BaseError.New("Unable to locate metadata for music video")).AsTask());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> UpdateMetadata(
|
private async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> UpdateMetadata(
|
||||||
MediaItemScanResult<MusicVideo> result)
|
MediaItemScanResult<MusicVideo> result)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MusicVideo musicVideo = result.Item;
|
MusicVideo musicVideo = result.Item;
|
||||||
return await LocateNfoFile(musicVideo).Match<Task<Either<BaseError, MediaItemScanResult<MusicVideo>>>>(
|
await LocateNfoFile(musicVideo).Match(
|
||||||
async nfoFile =>
|
async nfoFile =>
|
||||||
{
|
{
|
||||||
bool shouldUpdate = Optional(musicVideo.MusicVideoMetadata).Flatten().HeadOrNone().Match(
|
bool shouldUpdate = Optional(musicVideo.MusicVideoMetadata).Flatten().HeadOrNone().Match(
|
||||||
@@ -189,11 +158,21 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
result.IsUpdated = true;
|
result.IsUpdated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
},
|
||||||
() => Left<BaseError, MediaItemScanResult<MusicVideo>>(
|
async () =>
|
||||||
BaseError.New("Unable to locate metadata for music video")).AsTask());
|
{
|
||||||
|
if (!Optional(musicVideo.MusicVideoMetadata).Flatten().Any())
|
||||||
|
{
|
||||||
|
string path = musicVideo.MediaVersions.Head().MediaFiles.Head().Path;
|
||||||
|
_logger.LogDebug("Refreshing {Attribute} for {Path}", "Fallback Metadata", path);
|
||||||
|
if (await _localMetadataProvider.RefreshFallbackMetadata(musicVideo))
|
||||||
|
{
|
||||||
|
result.IsUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,83 +25,35 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
|||||||
_dbConnection = dbConnection;
|
_dbConnection = dbConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Option<MusicVideo>> GetByMetadata(LibraryPath libraryPath, MusicVideoMetadata metadata)
|
public async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> GetOrAdd(
|
||||||
{
|
|
||||||
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
|
|
||||||
Option<int> maybeId = await dbContext.MusicVideoMetadata
|
|
||||||
.Where(s => s.Artist == metadata.Artist && s.Title == metadata.Title && s.Year == metadata.Year)
|
|
||||||
.Where(s => s.MusicVideo.LibraryPathId == libraryPath.Id)
|
|
||||||
.SingleOrDefaultAsync()
|
|
||||||
.Map(Optional)
|
|
||||||
.MapT(sm => sm.MusicVideoId);
|
|
||||||
|
|
||||||
return await maybeId.Match(
|
|
||||||
id =>
|
|
||||||
{
|
|
||||||
return dbContext.MusicVideos
|
|
||||||
.AsNoTracking()
|
|
||||||
.Include(mv => mv.MusicVideoMetadata)
|
|
||||||
.ThenInclude(mvm => mvm.Artwork)
|
|
||||||
.Include(mv => mv.MusicVideoMetadata)
|
|
||||||
.ThenInclude(mvm => mvm.Genres)
|
|
||||||
.Include(mv => mv.MusicVideoMetadata)
|
|
||||||
.ThenInclude(mvm => mvm.Tags)
|
|
||||||
.Include(mv => mv.MusicVideoMetadata)
|
|
||||||
.ThenInclude(mvm => mvm.Studios)
|
|
||||||
.Include(mv => mv.LibraryPath)
|
|
||||||
.ThenInclude(lp => lp.Library)
|
|
||||||
.Include(mv => mv.MediaVersions)
|
|
||||||
.ThenInclude(mv => mv.MediaFiles)
|
|
||||||
.Include(mv => mv.MediaVersions)
|
|
||||||
.ThenInclude(mv => mv.Streams)
|
|
||||||
.OrderBy(mv => mv.Id)
|
|
||||||
.SingleOrDefaultAsync(mv => mv.Id == id)
|
|
||||||
.Map(Optional);
|
|
||||||
},
|
|
||||||
() => Option<MusicVideo>.None.AsTask());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> Add(
|
|
||||||
LibraryPath libraryPath,
|
LibraryPath libraryPath,
|
||||||
string filePath,
|
string path)
|
||||||
MusicVideoMetadata metadata)
|
|
||||||
{
|
{
|
||||||
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
|
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
Option<MusicVideo> maybeExisting = await dbContext.MusicVideos
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(mv => mv.MusicVideoMetadata)
|
||||||
|
.ThenInclude(mvm => mvm.Artwork)
|
||||||
|
.Include(mv => mv.MusicVideoMetadata)
|
||||||
|
.ThenInclude(mvm => mvm.Genres)
|
||||||
|
.Include(mv => mv.MusicVideoMetadata)
|
||||||
|
.ThenInclude(mvm => mvm.Tags)
|
||||||
|
.Include(mv => mv.MusicVideoMetadata)
|
||||||
|
.ThenInclude(mvm => mvm.Studios)
|
||||||
|
.Include(mv => mv.LibraryPath)
|
||||||
|
.ThenInclude(lp => lp.Library)
|
||||||
|
.Include(mv => mv.MediaVersions)
|
||||||
|
.ThenInclude(mv => mv.MediaFiles)
|
||||||
|
.Include(mv => mv.MediaVersions)
|
||||||
|
.ThenInclude(mv => mv.Streams)
|
||||||
|
.OrderBy(i => i.MediaVersions.First().MediaFiles.First().Path)
|
||||||
|
.SingleOrDefaultAsync(i => i.MediaVersions.First().MediaFiles.First().Path == path);
|
||||||
|
|
||||||
try
|
return await maybeExisting.Match(
|
||||||
{
|
mediaItem =>
|
||||||
metadata.DateAdded = DateTime.UtcNow;
|
Right<BaseError, MediaItemScanResult<MusicVideo>>(
|
||||||
metadata.Genres ??= new List<Genre>();
|
new MediaItemScanResult<MusicVideo>(mediaItem) { IsAdded = false }).AsTask(),
|
||||||
metadata.Tags ??= new List<Tag>();
|
async () => await AddMusicVideo(dbContext, libraryPath.Id, path));
|
||||||
metadata.Studios ??= new List<Studio>();
|
|
||||||
var musicVideo = new MusicVideo
|
|
||||||
{
|
|
||||||
LibraryPathId = libraryPath.Id,
|
|
||||||
MusicVideoMetadata = new List<MusicVideoMetadata> { metadata },
|
|
||||||
MediaVersions = new List<MediaVersion>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
MediaFiles = new List<MediaFile>
|
|
||||||
{
|
|
||||||
new() { Path = filePath }
|
|
||||||
},
|
|
||||||
Streams = new List<MediaStream>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await dbContext.MusicVideos.AddAsync(musicVideo);
|
|
||||||
await dbContext.SaveChangesAsync();
|
|
||||||
await dbContext.Entry(musicVideo).Reference(s => s.LibraryPath).LoadAsync();
|
|
||||||
await dbContext.Entry(musicVideo.LibraryPath).Reference(lp => lp.Library).LoadAsync();
|
|
||||||
|
|
||||||
return new MediaItemScanResult<MusicVideo>(musicVideo) { IsAdded = true };
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BaseError.New(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IEnumerable<string>> FindMusicVideoPaths(LibraryPath libraryPath) =>
|
public Task<IEnumerable<string>> FindMusicVideoPaths(LibraryPath libraryPath) =>
|
||||||
@@ -179,5 +131,40 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
|||||||
.SingleOrDefaultAsync(m => m.Id == musicVideoId)
|
.SingleOrDefaultAsync(m => m.Id == musicVideoId)
|
||||||
.Map(Optional);
|
.Map(Optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<Either<BaseError, MediaItemScanResult<MusicVideo>>> AddMusicVideo(
|
||||||
|
TvContext dbContext,
|
||||||
|
int libraryPathId,
|
||||||
|
string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var musicVideo = new MusicVideo
|
||||||
|
{
|
||||||
|
LibraryPathId = libraryPathId,
|
||||||
|
MediaVersions = new List<MediaVersion>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
MediaFiles = new List<MediaFile>
|
||||||
|
{
|
||||||
|
new() { Path = path }
|
||||||
|
},
|
||||||
|
Streams = new List<MediaStream>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await dbContext.MusicVideos.AddAsync(musicVideo);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
await dbContext.Entry(musicVideo).Reference(m => m.LibraryPath).LoadAsync();
|
||||||
|
await dbContext.Entry(musicVideo.LibraryPath).Reference(lp => lp.Library).LoadAsync();
|
||||||
|
return new MediaItemScanResult<MusicVideo>(musicVideo) { IsAdded = true };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BaseError.New(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user