From 409e1cca9459cb485c222acf70f57c27df06119a Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 25 Jan 2014 23:14:55 -0800 Subject: [PATCH] No more dupes and house cleaner added --- .../CleanupOrphanedMetadataFilesFixture.cs | 86 +++++++++++++++++++ .../NzbDrone.Core.Test.csproj | 1 + src/NzbDrone.Core/History/HistoryService.cs | 2 +- .../CleanupOrphanedMetadataFiles.cs | 50 +++++++++++ .../MediaCover/MediaCoverService.cs | 14 ++- .../MediaCover/MediaCoversUpdatedEvent.cs | 15 ++++ .../MediaFiles/MediaFileRepository.cs | 14 --- .../MediaFiles/MediaFileService.cs | 7 -- .../MetaData/Consumers/Fake/Fake.cs | 7 +- .../MetaData/Consumers/Xbmc/XbmcMetadata.cs | 47 +++++----- src/NzbDrone.Core/MetaData/IMetadata.cs | 5 +- src/NzbDrone.Core/MetaData/MetadataService.cs | 15 +++- src/NzbDrone.Core/MetaData/MetadataType.cs | 11 +-- .../Metadata/ExistingMetadataService.cs | 26 ++++-- src/NzbDrone.Core/Metadata/MetadataBase.cs | 2 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 4 +- 16 files changed, 235 insertions(+), 71 deletions(-) create mode 100644 src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMetadataFilesFixture.cs create mode 100644 src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs create mode 100644 src/NzbDrone.Core/MediaCover/MediaCoversUpdatedEvent.cs diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMetadataFilesFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMetadataFilesFixture.cs new file mode 100644 index 000000000..1eed6de95 --- /dev/null +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMetadataFilesFixture.cs @@ -0,0 +1,86 @@ +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Housekeeping.Housekeepers; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Metadata.Files; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.Housekeeping.Housekeepers +{ + [TestFixture] + public class CleanupOrphanedMetadataFilesFixture : DbTest + { + [Test] + public void should_delete_metadata_files_that_dont_have_a_coresponding_series() + { + var metadataFile = Builder.CreateNew() + .With(m => m.EpisodeFileId = null) + .BuildNew(); + + Db.Insert(metadataFile); + Subject.Clean(); + AllStoredModels.Should().BeEmpty(); + } + + [Test] + public void should_not_delete_metadata_files_that_have_a_coresponding_series() + { + var series = Builder.CreateNew() + .BuildNew(); + + Db.Insert(series); + + var metadataFile = Builder.CreateNew() + .With(m => m.SeriesId = series.Id) + .With(m => m.EpisodeFileId = null) + .BuildNew(); + + Db.Insert(metadataFile); + Subject.Clean(); + AllStoredModels.Should().HaveCount(1); + } + + [Test] + public void should_delete_metadata_files_that_dont_have_a_coresponding_episode_file() + { + var series = Builder.CreateNew() + .BuildNew(); + + Db.Insert(series); + + var metadataFile = Builder.CreateNew() + .With(m => m.SeriesId = series.Id) + .With(m => m.EpisodeFileId = 10) + .BuildNew(); + + Db.Insert(metadataFile); + Subject.Clean(); + AllStoredModels.Should().BeEmpty(); + } + + [Test] + public void should_not_delete_metadata_files_that_have_a_coresponding_episode_file() + { + var series = Builder.CreateNew() + .BuildNew(); + + var episodeFile = Builder.CreateNew() + .BuildNew(); + + Db.Insert(series); + Db.Insert(episodeFile); + + var metadataFile = Builder.CreateNew() + .With(m => m.SeriesId = series.Id) + .With(m => m.EpisodeFileId = episodeFile.Id) + .BuildNew(); + + Db.Insert(metadataFile); + Subject.Clean(); + AllStoredModels.Should().HaveCount(1); + } + } +} diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 5c72045ef..bb3fa1367 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -135,6 +135,7 @@ + diff --git a/src/NzbDrone.Core/History/HistoryService.cs b/src/NzbDrone.Core/History/HistoryService.cs index 28e8c0c72..41868977c 100644 --- a/src/NzbDrone.Core/History/HistoryService.cs +++ b/src/NzbDrone.Core/History/HistoryService.cs @@ -120,7 +120,7 @@ namespace NzbDrone.Core.History public void Handle(EpisodeImportedEvent message) { - if (message.NewDownload) + if (!message.NewDownload) { return; } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs new file mode 100644 index 000000000..a54497e30 --- /dev/null +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMetadataFiles.cs @@ -0,0 +1,50 @@ +using NLog; +using NzbDrone.Core.Datastore; + +namespace NzbDrone.Core.Housekeeping.Housekeepers +{ + public class CleanupOrphanedMetadataFiles : IHousekeepingTask + { + private readonly IDatabase _database; + private readonly Logger _logger; + + public CleanupOrphanedMetadataFiles(IDatabase database, Logger logger) + { + _database = database; + _logger = logger; + } + + public void Clean() + { + _logger.Trace("Running orphaned episode files cleanup"); + + DeleteOrphanedBySeries(); + DeleteOrphanedByEpisodeFile(); + } + + private void DeleteOrphanedBySeries() + { + var mapper = _database.GetDataMapper(); + + mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles + WHERE Id IN ( + SELECT MetadataFiles.Id FROM MetadataFiles + LEFT OUTER JOIN Series + ON MetadataFiles.SeriesId = Series.Id + WHERE Series.Id IS NULL)"); + } + + private void DeleteOrphanedByEpisodeFile() + { + var mapper = _database.GetDataMapper(); + + mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles + WHERE Id IN ( + SELECT MetadataFiles.Id FROM MetadataFiles + LEFT OUTER JOIN EpisodeFiles + ON MetadataFiles.EpisodeFileId = EpisodeFiles.Id + WHERE MetadataFiles.EpisodeFileId > 0 + AND EpisodeFiles.Id IS NULL)"); + } + } +} diff --git a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs index f9b0ebbc5..a208f28bd 100644 --- a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -17,6 +17,7 @@ namespace NzbDrone.Core.MediaCover { void ConvertToLocalUrls(int seriesId, IEnumerable covers); string GetCoverPath(int seriesId, MediaCoverTypes mediaCoverTypes); + } public class MediaCoverService : @@ -28,17 +29,24 @@ namespace NzbDrone.Core.MediaCover private readonly IDiskProvider _diskProvider; private readonly ICoverExistsSpecification _coverExistsSpecification; private readonly IConfigFileProvider _configFileProvider; + private readonly IEventAggregator _eventAggregator; private readonly Logger _logger; private readonly string _coverRootFolder; - public MediaCoverService(IHttpProvider httpProvider, IDiskProvider diskProvider, IAppFolderInfo appFolderInfo, - ICoverExistsSpecification coverExistsSpecification, IConfigFileProvider configFileProvider, Logger logger) + public MediaCoverService(IHttpProvider httpProvider, + IDiskProvider diskProvider, + IAppFolderInfo appFolderInfo, + ICoverExistsSpecification coverExistsSpecification, + IConfigFileProvider configFileProvider, + IEventAggregator eventAggregator, + Logger logger) { _httpProvider = httpProvider; _diskProvider = diskProvider; _coverExistsSpecification = coverExistsSpecification; _configFileProvider = configFileProvider; + _eventAggregator = eventAggregator; _logger = logger; _coverRootFolder = appFolderInfo.GetMediaCoverPath(); @@ -99,12 +107,12 @@ namespace NzbDrone.Core.MediaCover _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url); _httpProvider.DownloadFile(cover.Url, fileName); - } public void HandleAsync(SeriesUpdatedEvent message) { EnsureCovers(message.Series); + _eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Series)); } public void HandleAsync(SeriesDeletedEvent message) diff --git a/src/NzbDrone.Core/MediaCover/MediaCoversUpdatedEvent.cs b/src/NzbDrone.Core/MediaCover/MediaCoversUpdatedEvent.cs new file mode 100644 index 000000000..7335f7f9b --- /dev/null +++ b/src/NzbDrone.Core/MediaCover/MediaCoversUpdatedEvent.cs @@ -0,0 +1,15 @@ +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.MediaCover +{ + public class MediaCoversUpdatedEvent : IEvent + { + public Series Series { get; set; } + + public MediaCoversUpdatedEvent(Series series) + { + Series = series; + } + } +} diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs b/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs index fd7af51a4..0a7fe8a70 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; @@ -12,7 +9,6 @@ namespace NzbDrone.Core.MediaFiles { List GetFilesBySeries(int seriesId); List GetFilesBySeason(int seriesId, int seasonNumber); - EpisodeFile FindFileByPath(string path, bool includeExtension = true); } @@ -34,15 +30,5 @@ namespace NzbDrone.Core.MediaFiles .AndWhere(c => c.SeasonNumber == seasonNumber) .ToList(); } - - public EpisodeFile FindFileByPath(string path, bool includeExtension = true) - { - if (includeExtension) - { - return Query.SingleOrDefault(c => c.Path == path); - } - - return Query.SingleOrDefault(c => c.Path.StartsWith(Path.ChangeExtension(path, ""))); - } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileService.cs b/src/NzbDrone.Core/MediaFiles/MediaFileService.cs index 834d4dd6c..3bc146fad 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileService.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using NLog; @@ -19,7 +18,6 @@ namespace NzbDrone.Core.MediaFiles List FilterExistingFiles(List files, int seriesId); EpisodeFile Get(int id); List Get(IEnumerable ids); - EpisodeFile FindByPath(string path, bool includeExtension = true); } public class MediaFileService : IMediaFileService, IHandleAsync @@ -83,11 +81,6 @@ namespace NzbDrone.Core.MediaFiles return _mediaFileRepository.Get(ids).ToList(); } - public EpisodeFile FindByPath(string path, bool includeExtension = true) - { - return _mediaFileRepository.FindFileByPath(path, includeExtension); - } - public void HandleAsync(SeriesDeletedEvent message) { var files = GetFilesBySeries(message.Series.Id); diff --git a/src/NzbDrone.Core/MetaData/Consumers/Fake/Fake.cs b/src/NzbDrone.Core/MetaData/Consumers/Fake/Fake.cs index d91467fb2..43361b552 100644 --- a/src/NzbDrone.Core/MetaData/Consumers/Fake/Fake.cs +++ b/src/NzbDrone.Core/MetaData/Consumers/Fake/Fake.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -26,17 +27,17 @@ namespace NzbDrone.Core.Metadata.Consumers.Fake _logger = logger; } - public override void OnSeriesUpdated(Tv.Series series) + public override void OnSeriesUpdated(Series series, List existingMetadataFiles) { throw new NotImplementedException(); } - public override void OnEpisodeImport(Tv.Series series, EpisodeFile episodeFile, bool newDownload) + public override void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload) { throw new NotImplementedException(); } - public override void AfterRename(Tv.Series series) + public override void AfterRename(Series series) { throw new NotImplementedException(); } diff --git a/src/NzbDrone.Core/MetaData/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/MetaData/Consumers/Xbmc/XbmcMetadata.cs index d9eb45338..efad75344 100644 --- a/src/NzbDrone.Core/MetaData/Consumers/Xbmc/XbmcMetadata.cs +++ b/src/NzbDrone.Core/MetaData/Consumers/Xbmc/XbmcMetadata.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -47,24 +48,24 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc private static readonly Regex SeasonImagesRegex = new Regex(@"^season(?\d{2,}|-all|-specials)-(?poster|banner|fanart)\.(?: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) + public override void OnSeriesUpdated(Series series, List existingMetadataFiles) { if (Settings.SeriesMetadata) { EnsureFolder(series.Path); - WriteTvShowNfo(series); + WriteTvShowNfo(series, existingMetadataFiles); } if (Settings.SeriesImages) { EnsureFolder(series.Path); - WriteSeriesImages(series); + WriteSeriesImages(series, existingMetadataFiles); } if (Settings.SeasonImages) { EnsureFolder(series.Path); - WriteSeasonImages(series); + WriteSeasonImages(series, existingMetadataFiles); } } @@ -176,7 +177,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc return null; } - private void WriteTvShowNfo(Series series) + private void WriteTvShowNfo(Series series, List existingMetadataFiles) { _logger.Trace("Generating tvshow.nfo for: {0}", series.Title); var sb = new StringBuilder(); @@ -228,19 +229,20 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc _diskProvider.WriteAllText(path, doc.ToString()); - var metadata = new MetadataFile - { - SeriesId = series.Id, - Consumer = GetType().Name, - Type = MetadataType.SeriesMetadata, - RelativePath = DiskProvider.GetRelativePath(series.Path, path) - }; + var metadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.SeriesMetadata) ?? + new MetadataFile + { + SeriesId = series.Id, + Consumer = GetType().Name, + Type = MetadataType.SeriesMetadata, + RelativePath = DiskProvider.GetRelativePath(series.Path, path) + }; _eventAggregator.PublishEvent(new MetadataFileUpdated(metadata)); } } - private void WriteSeriesImages(Series series) + private void WriteSeriesImages(Series series, List existingMetadataFiles) { foreach (var image in series.Images) { @@ -256,7 +258,8 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc _diskProvider.CopyFile(source, destination, false); - var metadata = new MetadataFile + var metadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.SeriesImage) ?? + new MetadataFile { SeriesId = series.Id, Consumer = GetType().Name, @@ -268,7 +271,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc } } - private void WriteSeasonImages(Series series) + private void WriteSeasonImages(Series series, List existingMetadataFiles) { foreach (var season in series.Seasons) { @@ -285,12 +288,14 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc DownloadImage(series, image.Url, path); - var metadata = new MetadataFile + var metadata = existingMetadataFiles.SingleOrDefault(c => c.Type == MetadataType.SeasonImage && + c.SeasonNumber == season.SeasonNumber) ?? + new MetadataFile { SeriesId = series.Id, SeasonNumber = season.SeasonNumber, Consumer = GetType().Name, - Type = MetadataType.SeasonImage, + Type = MetadataType.SeriesMetadata, RelativePath = DiskProvider.GetRelativePath(series.Path, path) }; @@ -327,11 +332,11 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc details.Add(new XElement("displayepisode", episode.EpisodeNumber)); details.Add(new XElement("thumb", episode.Images.Single(i => i.CoverType == MediaCoverTypes.Screenshot).Url)); details.Add(new XElement("watched", "false")); -// details.Add(new XElement("credits", tvdbEpisode.Writer.FirstOrDefault())); -// details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault())); details.Add(new XElement("rating", episode.Ratings.Percentage)); - //Todo: get guest stars, will need trakt to have them + //Todo: get guest stars, writer and director + //details.Add(new XElement("credits", tvdbEpisode.Writer.FirstOrDefault())); + //details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault())); doc.Add(details); doc.Save(xw); @@ -360,7 +365,7 @@ namespace NzbDrone.Core.Metadata.Consumers.Xbmc { var screenshot = episodeFile.Episodes.Value.First().Images.Single(i => i.CoverType == MediaCoverTypes.Screenshot); - var filename = Path.GetFileNameWithoutExtension(episodeFile.Path) + "-thumb.jpg"; + var filename = Path.ChangeExtension(episodeFile.Path, "").Trim('.') + "-thumb.jpg"; DownloadImage(series, screenshot.Url, filename); diff --git a/src/NzbDrone.Core/MetaData/IMetadata.cs b/src/NzbDrone.Core/MetaData/IMetadata.cs index 2e606ac4a..02a51554c 100644 --- a/src/NzbDrone.Core/MetaData/IMetadata.cs +++ b/src/NzbDrone.Core/MetaData/IMetadata.cs @@ -1,4 +1,5 @@ -using NzbDrone.Core.MediaFiles; +using System.Collections.Generic; +using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Metadata.Files; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Tv; @@ -7,7 +8,7 @@ namespace NzbDrone.Core.Metadata { public interface IMetadata : IProvider { - void OnSeriesUpdated(Series series); + void OnSeriesUpdated(Series series, List existingMetadataFiles); void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload); void AfterRename(Series series); MetadataFile FindMetadataFile(Series series, string path); diff --git a/src/NzbDrone.Core/MetaData/MetadataService.cs b/src/NzbDrone.Core/MetaData/MetadataService.cs index 822cd2cf8..08708ab3e 100644 --- a/src/NzbDrone.Core/MetaData/MetadataService.cs +++ b/src/NzbDrone.Core/MetaData/MetadataService.cs @@ -1,31 +1,38 @@ using System.IO; +using System.Linq; using NLog; using NzbDrone.Common; +using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Metadata.Files; using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.Metadata { public class NotificationService - : IHandle, + : IHandle, IHandle, IHandle { private readonly IMetadataFactory _metadataFactory; + private readonly MetadataFileService _metadataFileService; private readonly Logger _logger; - public NotificationService(IMetadataFactory metadataFactory, Logger logger) + public NotificationService(IMetadataFactory metadataFactory, MetadataFileService metadataFileService, Logger logger) { _metadataFactory = metadataFactory; + _metadataFileService = metadataFileService; _logger = logger; } - public void Handle(SeriesUpdatedEvent message) + public void Handle(MediaCoversUpdatedEvent message) { + var seriesMetadata = _metadataFileService.GetFilesBySeries(message.Series.Id); + foreach (var consumer in _metadataFactory.Enabled()) { - consumer.OnSeriesUpdated(message.Series); + consumer.OnSeriesUpdated(message.Series, seriesMetadata.Where(c => c.Consumer == consumer.GetType().Name).ToList()); } } diff --git a/src/NzbDrone.Core/MetaData/MetadataType.cs b/src/NzbDrone.Core/MetaData/MetadataType.cs index 45470ffd3..5dbfa0b24 100644 --- a/src/NzbDrone.Core/MetaData/MetadataType.cs +++ b/src/NzbDrone.Core/MetaData/MetadataType.cs @@ -4,10 +4,11 @@ namespace NzbDrone.Core.Metadata { public enum MetadataType { - SeriesMetadata = 0, - EpisodeMetadata = 1, - SeriesImage = 2, - SeasonImage = 3, - EpisodeImage = 4 + Unknown = 0, + SeriesMetadata = 1, + EpisodeMetadata = 2, + SeriesImage = 3, + SeasonImage = 4, + EpisodeImage = 5 } } diff --git a/src/NzbDrone.Core/Metadata/ExistingMetadataService.cs b/src/NzbDrone.Core/Metadata/ExistingMetadataService.cs index e8bf85e0a..31c7d4947 100644 --- a/src/NzbDrone.Core/Metadata/ExistingMetadataService.cs +++ b/src/NzbDrone.Core/Metadata/ExistingMetadataService.cs @@ -6,6 +6,7 @@ using NzbDrone.Common; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Metadata.Files; +using NzbDrone.Core.Parser; using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.Metadata @@ -14,19 +15,19 @@ namespace NzbDrone.Core.Metadata { private readonly IDiskProvider _diskProvider; private readonly IMetadataFileService _metadataFileService; - private readonly IMediaFileService _mediaFileService; + private readonly IParsingService _parsingService; private readonly Logger _logger; private readonly List _consumers; public ExistingMetadataService(IDiskProvider diskProvider, IEnumerable consumers, IMetadataFileService metadataFileService, - IMediaFileService mediaFileService, + IParsingService parsingService, Logger logger) { _diskProvider = diskProvider; _metadataFileService = metadataFileService; - _mediaFileService = mediaFileService; + _parsingService = parsingService; _logger = logger; _consumers = consumers.ToList(); } @@ -52,14 +53,21 @@ namespace NzbDrone.Core.Metadata if (metadata.Type == MetadataType.EpisodeImage || metadata.Type == MetadataType.EpisodeMetadata) { - //TODO: replace this with parser lookup, otherwise its impossible to link thumbs without knowing too much about the consumers - //We might want to resort to parsing the file name and - //then finding it via episodes incase the file names get out of sync - var episodeFile = _mediaFileService.FindByPath(possibleMetadataFile, false); + var localEpisode = _parsingService.GetEpisodes(possibleMetadataFile, message.Series, false); - if (episodeFile == null) break; + if (localEpisode == null) + { + _logger.Trace("Cannot find related episodes for: {0}", possibleMetadataFile); + break; + } - metadata.EpisodeFileId = episodeFile.Id; + if (localEpisode.Episodes.DistinctBy(e => e.EpisodeFileId).Count() > 1) + { + _logger.Trace("Metadata file: {0} does not match existing files.", possibleMetadataFile); + break; + } + + metadata.EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId; } _metadataFileService.Upsert(metadata); diff --git a/src/NzbDrone.Core/Metadata/MetadataBase.cs b/src/NzbDrone.Core/Metadata/MetadataBase.cs index 9b8a454f1..29dc9a420 100644 --- a/src/NzbDrone.Core/Metadata/MetadataBase.cs +++ b/src/NzbDrone.Core/Metadata/MetadataBase.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Metadata public ProviderDefinition Definition { get; set; } - public abstract void OnSeriesUpdated(Series series); + public abstract void OnSeriesUpdated(Series series, List existingMetadataFiles); public abstract void OnEpisodeImport(Series series, EpisodeFile episodeFile, bool newDownload); public abstract void AfterRename(Series series); public abstract MetadataFile FindMetadataFile(Series series, string path); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 404ede750..b6773fa19 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -261,9 +261,10 @@ - + + @@ -296,6 +297,7 @@ +