Metadata cleanup and fixes

Fixed: Episode metadata will be renamed to match episode file names on refresh
Fixed: Episode metadata is renamed when episode file is renamed
pull/3113/head
Mark McDowall 10 years ago
parent e6e2f85d71
commit 7279b58a58

@ -1,4 +1,5 @@
using FluentValidation; using System;
using FluentValidation;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Validation.Paths; using NzbDrone.Core.Validation.Paths;
@ -11,7 +12,7 @@ namespace NzbDrone.Api.Config
{ {
SharedValidator.RuleFor(c => c.FileChmod).NotEmpty(); SharedValidator.RuleFor(c => c.FileChmod).NotEmpty();
SharedValidator.RuleFor(c => c.FolderChmod).NotEmpty(); SharedValidator.RuleFor(c => c.FolderChmod).NotEmpty();
SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator); SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator).When(c => !String.IsNullOrWhiteSpace(c.RecycleBin));
} }
} }
} }

@ -1,10 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
@ -16,19 +11,12 @@ namespace NzbDrone.Core.Metadata.Consumers.Fake
{ {
public class FakeMetadata : MetadataBase<FakeMetadataSettings> public class FakeMetadata : MetadataBase<FakeMetadataSettings>
{ {
private readonly IDiskProvider _diskProvider;
private readonly IHttpProvider _httpProvider;
private readonly Logger _logger;
public FakeMetadata(IDiskProvider diskProvider, IHttpProvider httpProvider, Logger logger) public FakeMetadata(IDiskProvider diskProvider, IHttpProvider httpProvider, Logger logger)
: base(diskProvider, httpProvider, logger) : base(diskProvider, httpProvider, logger)
{ {
_diskProvider = diskProvider;
_httpProvider = httpProvider;
_logger = logger;
} }
public override void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles) public override void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -38,7 +26,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Fake
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void AfterRename(Series series) public override void AfterRename(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
@ -53,8 +54,10 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
private static readonly Regex SeasonImagesRegex = new Regex(@"^season(?<season>\d{2,}|-all|-specials)-(?<type>poster|banner|fanart)\.(?:png|jpg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex SeasonImagesRegex = new Regex(@"^season(?<season>\d{2,}|-all|-specials)-(?<type>poster|banner|fanart)\.(?:png|jpg)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex EpisodeImageRegex = new Regex(@"-thumb\.(?:png|jpg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex EpisodeImageRegex = new Regex(@"-thumb\.(?:png|jpg)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public override void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles) public override void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles)
{ {
var metadataFiles = new List<MetadataFile>();
if (!_diskProvider.FolderExists(series.Path)) if (!_diskProvider.FolderExists(series.Path))
{ {
_logger.Info("Series folder does not exist, skipping metadata creation"); _logger.Info("Series folder does not exist, skipping metadata creation");
@ -63,26 +66,24 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
if (Settings.SeriesMetadata) if (Settings.SeriesMetadata)
{ {
WriteTvShowNfo(series, existingMetadataFiles); metadataFiles.Add(WriteTvShowNfo(series, existingMetadataFiles));
} }
if (Settings.SeriesImages) if (Settings.SeriesImages)
{ {
WriteSeriesImages(series, existingMetadataFiles); metadataFiles.AddRange(WriteSeriesImages(series, existingMetadataFiles));
} }
if (Settings.SeasonImages) if (Settings.SeasonImages)
{ {
WriteSeasonImages(series, existingMetadataFiles); metadataFiles.AddRange(WriteSeasonImages(series, existingMetadataFiles));
} }
var episodeFiles = GetEpisodeFiles(series.Id);
foreach (var episodeFile in episodeFiles) foreach (var episodeFile in episodeFiles)
{ {
if (Settings.EpisodeMetadata) if (Settings.EpisodeMetadata)
{ {
WriteEpisodeNfo(series, episodeFile, existingMetadataFiles); metadataFiles.Add(WriteEpisodeNfo(series, episodeFile, existingMetadataFiles));
} }
} }
@ -90,56 +91,85 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
{ {
if (Settings.EpisodeImages) if (Settings.EpisodeImages)
{ {
WriteEpisodeImages(series, episodeFile, existingMetadataFiles); var metadataFile = WriteEpisodeImages(series, episodeFile, existingMetadataFiles);
if (metadataFile != null)
{
metadataFiles.Add(metadataFile);
}
} }
} }
_eventAggregator.PublishEvent(new MetadataFilesUpdated(metadataFiles));
} }
public override void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload) public override void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload)
{ {
var metadataFiles = new List<MetadataFile>();
if (Settings.EpisodeMetadata) if (Settings.EpisodeMetadata)
{ {
WriteEpisodeNfo(series, episodeFile, new List<MetadataFile>()); metadataFiles.Add(WriteEpisodeNfo(series, episodeFile, new List<MetadataFile>()));
} }
if (Settings.EpisodeImages) if (Settings.EpisodeImages)
{ {
var metadataFile = WriteEpisodeImages(series, episodeFile, new List<MetadataFile>());
if (metadataFile != null)
{
metadataFiles.Add(metadataFile);
}
WriteEpisodeImages(series, episodeFile, new List<MetadataFile>()); WriteEpisodeImages(series, episodeFile, new List<MetadataFile>());
} }
_eventAggregator.PublishEvent(new MetadataFilesUpdated(metadataFiles));
} }
public override void AfterRename(Series series) public override void AfterRename(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles)
{ {
//TODO: This should be part of the base class, but could be overwritten if the logic needs to be different var episodeFilesMetadata = existingMetadataFiles.Where(c => c.EpisodeFileId > 0).ToList();
//or it could be done in MetadataService instead of having each metadata consumer do it var updatedMetadataFiles = new List<MetadataFile>();
var episodeFiles = _mediaFileService.GetFilesBySeries(series.Id);
var episodeFilesMetadata = _metadataFileService.GetFilesBySeries(series.Id).Where(c => c.EpisodeFileId > 0).ToList();
foreach (var episodeFile in episodeFiles) foreach (var episodeFile in episodeFiles)
{ {
var metadataFiles = episodeFilesMetadata.Where(m => m.EpisodeFileId == episodeFile.Id).ToList(); var metadataFiles = episodeFilesMetadata.Where(m => m.EpisodeFileId == episodeFile.Id).ToList();
var episodeFilenameWithoutExtension =
Path.GetFileNameWithoutExtension(DiskProviderBase.GetRelativePath(series.Path, episodeFile.Path));
foreach (var metadataFile in metadataFiles) foreach (var metadataFile in metadataFiles)
{ {
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(metadataFile.RelativePath); string newFilename;
var extension = Path.GetExtension(metadataFile.RelativePath);
if (!fileNameWithoutExtension.Equals(episodeFilenameWithoutExtension)) if (metadataFile.Type == MetadataType.EpisodeImage)
{ {
var source = Path.Combine(series.Path, metadataFile.RelativePath); newFilename = GetEpisodeImageFilename(episodeFile.Path);
var destination = Path.Combine(series.Path, fileNameWithoutExtension + extension); }
_diskProvider.MoveFile(source, destination); else if (metadataFile.Type == MetadataType.EpisodeMetadata)
metadataFile.RelativePath = fileNameWithoutExtension + extension; {
newFilename = GetEpisodeNfoFilename(episodeFile.Path);
}
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadataFile)); else
{
_logger.Trace("Unknown episode file metadata: {0}", metadataFile.RelativePath);
continue;
} }
var existingFilename = Path.Combine(series.Path, metadataFile.RelativePath);
if (!newFilename.PathEquals(existingFilename))
{
_diskProvider.MoveFile(existingFilename, newFilename);
metadataFile.RelativePath = DiskProviderBase.GetRelativePath(series.Path, newFilename);
updatedMetadataFiles.Add(metadataFile);
} }
} }
} }
_eventAggregator.PublishEvent(new MetadataFilesUpdated(updatedMetadataFiles));
}
public override MetadataFile FindMetadataFile(Series series, string path) public override MetadataFile FindMetadataFile(Series series, string path)
{ {
var filename = Path.GetFileName(path); var filename = Path.GetFileName(path);
@ -205,7 +235,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
return null; return null;
} }
private void WriteTvShowNfo(Series series, List<MetadataFile> existingMetadataFiles) private MetadataFile WriteTvShowNfo(Series series, List<MetadataFile> existingMetadataFiles)
{ {
_logger.Trace("Generating tvshow.nfo for: {0}", series.Title); _logger.Trace("Generating tvshow.nfo for: {0}", series.Title);
var sb = new StringBuilder(); var sb = new StringBuilder();
@ -266,11 +296,11 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
RelativePath = DiskProviderBase.GetRelativePath(series.Path, path) RelativePath = DiskProviderBase.GetRelativePath(series.Path, path)
}; };
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); return metadata;
} }
} }
private void WriteSeriesImages(Series series, List<MetadataFile> existingMetadataFiles) private IEnumerable<MetadataFile> WriteSeriesImages(Series series, List<MetadataFile> existingMetadataFiles)
{ {
foreach (var image in series.Images) foreach (var image in series.Images)
{ {
@ -295,11 +325,11 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
RelativePath = DiskProviderBase.GetRelativePath(series.Path, destination) RelativePath = DiskProviderBase.GetRelativePath(series.Path, destination)
}; };
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); yield return metadata;
} }
} }
private void WriteSeasonImages(Series series, List<MetadataFile> existingMetadataFiles) private IEnumerable<MetadataFile> WriteSeasonImages(Series series, List<MetadataFile> existingMetadataFiles)
{ {
foreach (var season in series.Seasons) foreach (var season in series.Seasons)
{ {
@ -327,14 +357,28 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
RelativePath = DiskProviderBase.GetRelativePath(series.Path, path) RelativePath = DiskProviderBase.GetRelativePath(series.Path, path)
}; };
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); yield return metadata;
} }
} }
} }
private void WriteEpisodeNfo(Series series, EpisodeFile episodeFile, List<MetadataFile> existingMetadataFiles) private MetadataFile WriteEpisodeNfo(Series series, EpisodeFile episodeFile, List<MetadataFile> existingMetadataFiles)
{
var filename = GetEpisodeNfoFilename(episodeFile.Path);
var relativePath = DiskProviderBase.GetRelativePath(series.Path, filename);
var existingMetadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.EpisodeMetadata &&
c.EpisodeFileId == episodeFile.Id);
if (existingMetadata != null)
{
var fullPath = Path.Combine(series.Path, existingMetadata.RelativePath);
if (!filename.PathEquals(fullPath))
{ {
var filename = episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo"); _diskProvider.MoveFile(fullPath, filename);
existingMetadata.RelativePath = relativePath;
}
}
_logger.Debug("Generating {0} for: {1}", filename, episodeFile.Path); _logger.Debug("Generating {0} for: {1}", filename, episodeFile.Path);
@ -390,8 +434,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
_logger.Debug("Saving episodedetails to: {0}", filename); _logger.Debug("Saving episodedetails to: {0}", filename);
_diskProvider.WriteAllText(filename, xmlResult.Trim(Environment.NewLine.ToCharArray())); _diskProvider.WriteAllText(filename, xmlResult.Trim(Environment.NewLine.ToCharArray()));
var metadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.EpisodeMetadata && var metadata = existingMetadata ??
c.EpisodeFileId == episodeFile.Id) ??
new MetadataFile new MetadataFile
{ {
SeriesId = series.Id, SeriesId = series.Id,
@ -401,19 +444,38 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
RelativePath = DiskProviderBase.GetRelativePath(series.Path, filename) RelativePath = DiskProviderBase.GetRelativePath(series.Path, filename)
}; };
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); return metadata;
} }
private void WriteEpisodeImages(Series series, EpisodeFile episodeFile, List<MetadataFile> existingMetadataFiles) private MetadataFile WriteEpisodeImages(Series series, EpisodeFile episodeFile, List<MetadataFile> existingMetadataFiles)
{
var screenshot = episodeFile.Episodes.Value.First().Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
if (screenshot == null)
{ {
var screenshot = episodeFile.Episodes.Value.First().Images.Single(i => i.CoverType == MediaCoverTypes.Screenshot); _logger.Trace("Episode screenshot not available");
return null;
}
var filename = Path.ChangeExtension(episodeFile.Path, "").Trim('.') + "-thumb.jpg"; var filename = GetEpisodeImageFilename(episodeFile.Path);
var relativePath = DiskProviderBase.GetRelativePath(series.Path, filename);
var existingMetadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.EpisodeImage &&
c.EpisodeFileId == episodeFile.Id);
if (existingMetadata != null)
{
var fullPath = Path.Combine(series.Path, existingMetadata.RelativePath);
if (!filename.PathEquals(fullPath))
{
_diskProvider.MoveFile(fullPath, filename);
existingMetadata.RelativePath = relativePath;
}
}
DownloadImage(series, screenshot.Url, filename); DownloadImage(series, screenshot.Url, filename);
var metadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.EpisodeImage && var metadata = existingMetadata ??
c.EpisodeFileId == episodeFile.Id) ??
new MetadataFile new MetadataFile
{ {
SeriesId = series.Id, SeriesId = series.Id,
@ -423,21 +485,17 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc
RelativePath = DiskProviderBase.GetRelativePath(series.Path, filename) RelativePath = DiskProviderBase.GetRelativePath(series.Path, filename)
}; };
_eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); return metadata;
} }
private List<EpisodeFile> GetEpisodeFiles(int seriesId) private string GetEpisodeNfoFilename(string episodeFilePath)
{ {
var episodeFiles = _mediaFileService.GetFilesBySeries(seriesId); return Path.ChangeExtension(episodeFilePath, "nfo");
var episodes = _episodeService.GetEpisodeBySeries(seriesId);
foreach (var episodeFile in episodeFiles)
{
var localEpisodeFile = episodeFile;
episodeFile.Episodes = new LazyList<Episode>(episodes.Where(e => e.EpisodeFileId == localEpisodeFile.Id));
} }
return episodeFiles; private string GetEpisodeImageFilename(string episodeFilePath)
{
return Path.ChangeExtension(episodeFilePath, "").Trim('.') + "-thumb.jpg";
} }
} }
} }

@ -0,0 +1,15 @@
using System.Collections.Generic;
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.Metadata.Files
{
public class MetadataFilesUpdated : IEvent
{
public List<MetadataFile> MetadataFiles { get; set; }
public MetadataFilesUpdated(List<MetadataFile> metadataFiles)
{
MetadataFiles = metadataFiles;
}
}
}

@ -8,9 +8,9 @@ namespace NzbDrone.Core.Metadata
{ {
public interface IMetadata : IProvider public interface IMetadata : IProvider
{ {
void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles); void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles);
void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload); void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload);
void AfterRename(Series series); void AfterRename(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles);
MetadataFile FindMetadataFile(Series series, string path); MetadataFile FindMetadataFile(Series series, string path);
} }
} }

@ -1,9 +1,13 @@
using System.Linq; using System.Collections.Generic;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Metadata.Files; using NzbDrone.Core.Metadata.Files;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Metadata namespace NzbDrone.Core.Metadata
{ {
@ -15,16 +19,22 @@ namespace NzbDrone.Core.Metadata
private readonly IMetadataFactory _metadataFactory; private readonly IMetadataFactory _metadataFactory;
private readonly IMetadataFileService _metadataFileService; private readonly IMetadataFileService _metadataFileService;
private readonly ICleanMetadataService _cleanMetadataService; private readonly ICleanMetadataService _cleanMetadataService;
private readonly IMediaFileService _mediaFileService;
private readonly IEpisodeService _episodeService;
private readonly Logger _logger; private readonly Logger _logger;
public MetadataService(IMetadataFactory metadataFactory, public MetadataService(IMetadataFactory metadataFactory,
IMetadataFileService metadataFileService, IMetadataFileService metadataFileService,
ICleanMetadataService cleanMetadataService, ICleanMetadataService cleanMetadataService,
IMediaFileService mediaFileService,
IEpisodeService episodeService,
Logger logger) Logger logger)
{ {
_metadataFactory = metadataFactory; _metadataFactory = metadataFactory;
_metadataFileService = metadataFileService; _metadataFileService = metadataFileService;
_cleanMetadataService = cleanMetadataService; _cleanMetadataService = cleanMetadataService;
_mediaFileService = mediaFileService;
_episodeService = episodeService;
_logger = logger; _logger = logger;
} }
@ -35,7 +45,7 @@ namespace NzbDrone.Core.Metadata
foreach (var consumer in _metadataFactory.Enabled()) foreach (var consumer in _metadataFactory.Enabled())
{ {
consumer.OnSeriesUpdated(message.Series, seriesMetadata.Where(c => c.Consumer == consumer.GetType().Name).ToList()); consumer.OnSeriesUpdated(message.Series, GetMetadataFilesForConsumer(consumer, seriesMetadata), GetEpisodeFiles(message.Series.Id));
} }
} }
@ -49,10 +59,31 @@ namespace NzbDrone.Core.Metadata
public void Handle(SeriesRenamedEvent message) public void Handle(SeriesRenamedEvent message)
{ {
var seriesMetadata = _metadataFileService.GetFilesBySeries(message.Series.Id);
foreach (var consumer in _metadataFactory.Enabled()) foreach (var consumer in _metadataFactory.Enabled())
{ {
consumer.AfterRename(message.Series); consumer.AfterRename(message.Series, GetMetadataFilesForConsumer(consumer, seriesMetadata), GetEpisodeFiles(message.Series.Id));
}
}
private List<EpisodeFile> GetEpisodeFiles(int seriesId)
{
var episodeFiles = _mediaFileService.GetFilesBySeries(seriesId);
var episodes = _episodeService.GetEpisodeBySeries(seriesId);
foreach (var episodeFile in episodeFiles)
{
var localEpisodeFile = episodeFile;
episodeFile.Episodes = new LazyList<Episode>(episodes.Where(e => e.EpisodeFileId == localEpisodeFile.Id));
}
return episodeFiles;
} }
private List<MetadataFile> GetMetadataFilesForConsumer(IMetadata consumer, List<MetadataFile> seriesMetadata)
{
return seriesMetadata.Where(c => c.Consumer == consumer.GetType().Name).ToList();
} }
} }
} }

@ -12,7 +12,7 @@ using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.Metadata namespace NzbDrone.Core.Metadata
{ {
public class ExistingMetadataService : IHandleAsync<SeriesUpdatedEvent> public class ExistingMetadataService : IHandle<SeriesUpdatedEvent>
{ {
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IMetadataFileService _metadataFileService; private readonly IMetadataFileService _metadataFileService;
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Metadata
_consumers = consumers.ToList(); _consumers = consumers.ToList();
} }
public void HandleAsync(SeriesUpdatedEvent message) public void Handle(SeriesUpdatedEvent message)
{ {
if (!_diskProvider.FolderExists(message.Series.Path)) return; if (!_diskProvider.FolderExists(message.Series.Path)) return;
@ -43,6 +43,8 @@ namespace NzbDrone.Core.Metadata
var possibleMetadataFiles = filesOnDisk.Where(c => !MediaFileExtensions.Extensions.Contains(Path.GetExtension(c).ToLower())).ToList(); var possibleMetadataFiles = filesOnDisk.Where(c => !MediaFileExtensions.Extensions.Contains(Path.GetExtension(c).ToLower())).ToList();
var filteredFiles = _metadataFileService.FilterExistingFiles(possibleMetadataFiles, message.Series); var filteredFiles = _metadataFileService.FilterExistingFiles(possibleMetadataFiles, message.Series);
var metadataFiles = new List<MetadataFile>();
foreach (var possibleMetadataFile in filteredFiles) foreach (var possibleMetadataFile in filteredFiles)
{ {
foreach (var consumer in _consumers) foreach (var consumer in _consumers)
@ -71,9 +73,11 @@ namespace NzbDrone.Core.Metadata
metadata.EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId; metadata.EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId;
} }
_metadataFileService.Upsert(metadata); metadataFiles.Add(metadata);
} }
} }
_metadataFileService.Upsert(metadataFiles);
} }
} }
} }

@ -18,14 +18,14 @@ namespace NzbDrone.Core.Metadata.Files
List<MetadataFile> GetFilesByEpisodeFile(int episodeFileId); List<MetadataFile> GetFilesByEpisodeFile(int episodeFileId);
MetadataFile FindByPath(string path); MetadataFile FindByPath(string path);
List<string> FilterExistingFiles(List<string> files, Series series); List<string> FilterExistingFiles(List<string> files, Series series);
MetadataFile Upsert(MetadataFile metadataFile); void Upsert(List<MetadataFile> metadataFiles);
void Delete(int id); void Delete(int id);
} }
public class MetadataFileService : IMetadataFileService, public class MetadataFileService : IMetadataFileService,
IHandleAsync<SeriesDeletedEvent>, IHandleAsync<SeriesDeletedEvent>,
IHandleAsync<EpisodeFileDeletedEvent>, IHandleAsync<EpisodeFileDeletedEvent>,
IHandle<MetadataFileUpdated> IHandle<MetadataFilesUpdated>
{ {
private readonly IMetadataFileRepository _repository; private readonly IMetadataFileRepository _repository;
private readonly ISeriesService _seriesService; private readonly ISeriesService _seriesService;
@ -67,10 +67,12 @@ namespace NzbDrone.Core.Metadata.Files
return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList(); return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList();
} }
public MetadataFile Upsert(MetadataFile metadataFile) public void Upsert(List<MetadataFile> metadataFiles)
{ {
metadataFile.LastUpdated = DateTime.UtcNow; metadataFiles.ForEach(m => m.LastUpdated = DateTime.UtcNow);
return _repository.Upsert(metadataFile);
_repository.InsertMany(metadataFiles.Where(m => m.Id == 0).ToList());
_repository.UpdateMany(metadataFiles.Where(m => m.Id > 0).ToList());
} }
public void Delete(int id) public void Delete(int id)
@ -103,9 +105,9 @@ namespace NzbDrone.Core.Metadata.Files
_repository.DeleteForEpisodeFile(episodeFile.Id); _repository.DeleteForEpisodeFile(episodeFile.Id);
} }
public void Handle(MetadataFileUpdated message) public void Handle(MetadataFilesUpdated message)
{ {
Upsert(message.Metadata); Upsert(message.MetadataFiles);
} }
} }
} }

@ -1,14 +0,0 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.Metadata.Files
{
public class MetadataFileUpdated : IEvent
{
public MetadataFile Metadata { get; set; }
public MetadataFileUpdated(MetadataFile metadata)
{
Metadata = metadata;
}
}
}

@ -42,9 +42,9 @@ namespace NzbDrone.Core.Metadata
public ProviderDefinition Definition { get; set; } public ProviderDefinition Definition { get; set; }
public abstract void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles); public abstract void OnSeriesUpdated(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles);
public abstract void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload); public abstract void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload);
public abstract void AfterRename(Series series); public abstract void AfterRename(Series series, List<MetadataFile> existingMetadataFiles, List<EpisodeFile> episodeFiles);
public abstract MetadataFile FindMetadataFile(Series series, string path); public abstract MetadataFile FindMetadataFile(Series series, string path);
protected TSettings Settings protected TSettings Settings

@ -344,10 +344,10 @@
<Compile Include="Metadata\Consumers\Xbmc\XbmcMetadata.cs" /> <Compile Include="Metadata\Consumers\Xbmc\XbmcMetadata.cs" />
<Compile Include="Metadata\Consumers\Xbmc\XbmcMetadataSettings.cs" /> <Compile Include="Metadata\Consumers\Xbmc\XbmcMetadataSettings.cs" />
<Compile Include="Metadata\ExistingMetadataService.cs" /> <Compile Include="Metadata\ExistingMetadataService.cs" />
<Compile Include="Metadata\Files\MetadataFilesUpdated.cs" />
<Compile Include="Metadata\Files\MetadataFile.cs" /> <Compile Include="Metadata\Files\MetadataFile.cs" />
<Compile Include="Metadata\Files\MetadataFileRepository.cs" /> <Compile Include="Metadata\Files\MetadataFileRepository.cs" />
<Compile Include="Metadata\Files\MetadataFileService.cs" /> <Compile Include="Metadata\Files\MetadataFileService.cs" />
<Compile Include="Metadata\Files\MetadataFileUpdated.cs" />
<Compile Include="Metadata\IMetadata.cs" /> <Compile Include="Metadata\IMetadata.cs" />
<Compile Include="Metadata\MetadataBase.cs" /> <Compile Include="Metadata\MetadataBase.cs" />
<Compile Include="MetadataSource\Trakt\TraktException.cs" /> <Compile Include="MetadataSource\Trakt\TraktException.cs" />

Loading…
Cancel
Save