From 448cfff76973c83ca0850e807dd0d63317b2f9f4 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Thu, 1 Mar 2018 17:09:36 +0100 Subject: [PATCH 1/4] Fixed: Recycle Metadata files on episode removal. --- .../Extras/Files/ExtraFileService.cs | 16 +++------------- .../Extras/Metadata/Files/MetadataFileService.cs | 2 -- .../Extras/Metadata/MetadataService.cs | 7 +++++-- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs b/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs index dc13ba41c..50bd5f369 100644 --- a/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs +++ b/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs @@ -49,8 +49,6 @@ namespace NzbDrone.Core.Extras.Files _logger = logger; } - public virtual bool PermanentlyDelete => false; - public List GetFilesBySeries(int seriesId) { return _repository.GetFilesBySeries(seriesId); @@ -122,17 +120,9 @@ namespace NzbDrone.Core.Extras.Files if (_diskProvider.FileExists(path)) { - if (PermanentlyDelete) - { - _diskProvider.DeleteFile(path); - } - - else - { - // Send extra files to the recycling bin so they can be recovered if necessary - var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(path)); - _recycleBinProvider.DeleteFile(path, subfolder); - } + // Send to the recycling bin so they can be recovered if necessary + var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(path)); + _recycleBinProvider.DeleteFile(path, subfolder); } } } diff --git a/src/NzbDrone.Core/Extras/Metadata/Files/MetadataFileService.cs b/src/NzbDrone.Core/Extras/Metadata/Files/MetadataFileService.cs index f5fc2ba69..b83bf0c90 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Files/MetadataFileService.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Files/MetadataFileService.cs @@ -16,7 +16,5 @@ namespace NzbDrone.Core.Extras.Metadata.Files : base(repository, seriesService, diskProvider, recycleBinProvider, logger) { } - - public override bool PermanentlyDelete => true; } } diff --git a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs index dbe4c1fba..4731655e7 100644 --- a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs +++ b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs @@ -19,6 +19,7 @@ namespace NzbDrone.Core.Extras.Metadata { private readonly IMetadataFactory _metadataFactory; private readonly ICleanMetadataService _cleanMetadataService; + private readonly IRecycleBinProvider _recycleBinProvider; private readonly IDiskTransferService _diskTransferService; private readonly IDiskProvider _diskProvider; private readonly IHttpClient _httpClient; @@ -29,6 +30,7 @@ namespace NzbDrone.Core.Extras.Metadata public MetadataService(IConfigService configService, IDiskProvider diskProvider, IDiskTransferService diskTransferService, + IRecycleBinProvider recycleBinProvider, IMetadataFactory metadataFactory, ICleanMetadataService cleanMetadataService, IHttpClient httpClient, @@ -39,6 +41,7 @@ namespace NzbDrone.Core.Extras.Metadata { _metadataFactory = metadataFactory; _cleanMetadataService = cleanMetadataService; + _recycleBinProvider = recycleBinProvider; _diskTransferService = diskTransferService; _diskProvider = diskProvider; _httpClient = httpClient; @@ -443,11 +446,11 @@ namespace NzbDrone.Core.Extras.Metadata _logger.Debug("Removing duplicate Metadata file: {0}", path); - _diskProvider.DeleteFile(path); + var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(path)); + _recycleBinProvider.DeleteFile(path, subfolder); _metadataFileService.Delete(file.Id); } - return matchingMetadataFiles.First(); } } From f0eba619f35cadf7574ce7362ebac1f99f91fff8 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Thu, 1 Mar 2018 17:11:04 +0100 Subject: [PATCH 2/4] Moved tests. --- .../Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs | 2 +- .../Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/NzbDrone.Core.Test/{ => Extras}/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs (97%) rename src/NzbDrone.Core.Test/{ => Extras}/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs (97%) diff --git a/src/NzbDrone.Core.Test/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs similarity index 97% rename from src/NzbDrone.Core.Test/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs rename to src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs index 6d4328b32..5e7a53ce3 100644 --- a/src/NzbDrone.Core.Test/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs +++ b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Roksbox/FindMetadataFileFixture.cs @@ -8,7 +8,7 @@ using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; using NzbDrone.Test.Common; -namespace NzbDrone.Core.Test.Metadata.Consumers.Roksbox +namespace NzbDrone.Core.Test.Extras.Metadata.Consumers.Roksbox { [TestFixture] public class FindMetadataFileFixture : CoreTest diff --git a/src/NzbDrone.Core.Test/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs similarity index 97% rename from src/NzbDrone.Core.Test/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs rename to src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs index 078744ec8..17f9d4f6e 100644 --- a/src/NzbDrone.Core.Test/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs +++ b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Wdtv/FindMetadataFileFixture.cs @@ -8,7 +8,7 @@ using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; using NzbDrone.Test.Common; -namespace NzbDrone.Core.Test.Metadata.Consumers.Wdtv +namespace NzbDrone.Core.Test.Extras.Metadata.Consumers.Wdtv { [TestFixture] public class FindMetadataFileFixture : CoreTest From d2849693795c85eeb76695864fd3f933a087c9db Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Thu, 1 Mar 2018 18:29:05 +0100 Subject: [PATCH 3/4] New: Detect Kodi .nfo vs Scene .nfo and handle as appropriate. Rename scene .nfo to .nfo-orig only when needed. --- .../Consumers/Xbmc/FindMetadataFileFixture.cs | 65 +++++++++++++++ .../NzbDrone.Core.Test.csproj | 5 +- src/NzbDrone.Core/Extras/ExtraService.cs | 26 ++++-- .../Metadata/Consumers/Xbmc/XbmcMetadata.cs | 20 ++++- .../Consumers/Xbmc/XbmcNfoDetector.cs | 40 +++++++++ .../Extras/Metadata/MetadataService.cs | 13 ++- .../Extras/Others/OtherExtraFileRenamer.cs | 82 +++++++++++++++++++ .../Extras/Others/OtherExtraService.cs | 6 -- .../EpisodeImport/ImportApprovedEpisodes.cs | 2 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 2 + 10 files changed, 238 insertions(+), 23 deletions(-) create mode 100644 src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Xbmc/FindMetadataFileFixture.cs create mode 100644 src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcNfoDetector.cs create mode 100644 src/NzbDrone.Core/Extras/Others/OtherExtraFileRenamer.cs diff --git a/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Xbmc/FindMetadataFileFixture.cs b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Xbmc/FindMetadataFileFixture.cs new file mode 100644 index 000000000..6f7043fec --- /dev/null +++ b/src/NzbDrone.Core.Test/Extras/Metadata/Consumers/Xbmc/FindMetadataFileFixture.cs @@ -0,0 +1,65 @@ +using System.IO; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Extras.Metadata; +using NzbDrone.Core.Extras.Metadata.Consumers.Xbmc; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.Extras.Metadata.Consumers.Xbmc +{ + [TestFixture] + public class FindMetadataFileFixture : CoreTest + { + private Series _series; + + [SetUp] + public void Setup() + { + _series = Builder.CreateNew() + .With(s => s.Path = @"C:\Test\TV\The.Series".AsOsAgnostic()) + .Build(); + } + + [Test] + public void should_return_null_if_filename_is_not_handled() + { + var path = Path.Combine(_series.Path, "file.jpg"); + + Subject.FindMetadataFile(_series, path).Should().BeNull(); + } + + [Test] + public void should_return_metadata_for_xbmc_nfo() + { + var path = Path.Combine(_series.Path, "the.series.s01e01.episode.nfo"); + + Mocker.GetMock() + .Setup(v => v.IsXbmcNfoFile(path)) + .Returns(true); + + Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.EpisodeMetadata); + + Mocker.GetMock() + .Verify(v => v.IsXbmcNfoFile(It.IsAny()), Times.Once()); + } + + [Test] + public void should_return_null_for_scene_nfo() + { + var path = Path.Combine(_series.Path, "the.series.s01e01.episode.nfo"); + + Mocker.GetMock() + .Setup(v => v.IsXbmcNfoFile(path)) + .Returns(false); + + Subject.FindMetadataFile(_series, path).Should().BeNull(); + + Mocker.GetMock() + .Verify(v => v.IsXbmcNfoFile(It.IsAny()), Times.Once()); + } + } +} diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index b2d7a3b0f..d29f8bb25 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -220,6 +220,7 @@ Always + @@ -340,8 +341,8 @@ - - + + diff --git a/src/NzbDrone.Core/Extras/ExtraService.cs b/src/NzbDrone.Core/Extras/ExtraService.cs index 99d9ec3a6..ce5b660b6 100644 --- a/src/NzbDrone.Core/Extras/ExtraService.cs +++ b/src/NzbDrone.Core/Extras/ExtraService.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Extras { public interface IExtraService { - void ImportExtraFiles(LocalEpisode localEpisode, EpisodeFile episodeFile, bool isReadOnly); + void ImportEpisode(LocalEpisode localEpisode, EpisodeFile episodeFile, bool isReadOnly); } public class ExtraService : IExtraService, @@ -48,15 +48,15 @@ namespace NzbDrone.Core.Extras _logger = logger; } - public void ImportExtraFiles(LocalEpisode localEpisode, EpisodeFile episodeFile, bool isReadOnly) + public void ImportEpisode(LocalEpisode localEpisode, EpisodeFile episodeFile, bool isReadOnly) { - var series = localEpisode.Series; - - foreach (var extraFileManager in _extraFileManagers) - { - extraFileManager.CreateAfterEpisodeImport(series, episodeFile); - } + ImportExtraFiles(localEpisode, episodeFile, isReadOnly); + + CreateAfterImport(localEpisode.Series, episodeFile); + } + private void ImportExtraFiles(LocalEpisode localEpisode, EpisodeFile episodeFile, bool isReadOnly) + { if (!_configService.ImportExtraFiles) { return; @@ -87,7 +87,7 @@ namespace NzbDrone.Core.Extras foreach (var extraFileManager in _extraFileManagers) { var extension = Path.GetExtension(matchingFilename); - var extraFile = extraFileManager.Import(series, episodeFile, matchingFilename, extension, isReadOnly); + var extraFile = extraFileManager.Import(localEpisode.Series, episodeFile, matchingFilename, extension, isReadOnly); if (extraFile != null) { @@ -102,6 +102,14 @@ namespace NzbDrone.Core.Extras } } + private void CreateAfterImport(Series series, EpisodeFile episodeFile) + { + foreach (var extraFileManager in _extraFileManagers) + { + extraFileManager.CreateAfterEpisodeImport(series, episodeFile); + } + } + public void Handle(MediaCoversUpdatedEvent message) { var series = message.Series; diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs index 6cfd5f2d0..096d7c889 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs @@ -18,14 +18,17 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc { public class XbmcMetadata : MetadataBase { - private readonly IMapCoversToLocal _mediaCoverService; private readonly Logger _logger; + private readonly IMapCoversToLocal _mediaCoverService; + private readonly IDetectXbmcNfo _detectNfo; - public XbmcMetadata(IMapCoversToLocal mediaCoverService, + public XbmcMetadata(IDetectXbmcNfo detectNfo, + IMapCoversToLocal mediaCoverService, Logger logger) { - _mediaCoverService = mediaCoverService; _logger = logger; + _mediaCoverService = mediaCoverService; + _detectNfo = detectNfo; } private static readonly Regex SeriesImagesRegex = new Regex(@"^(?poster|banner|fanart)\.(?:png|jpg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -114,7 +117,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc if (parseResult != null && !parseResult.FullSeason && - Path.GetExtension(filename).Equals(".nfo", StringComparison.OrdinalIgnoreCase)) + Path.GetExtension(filename).Equals(".nfo", StringComparison.OrdinalIgnoreCase) && + _detectNfo.IsXbmcNfoFile(path)) { metadata.Type = MetadataType.EpisodeMetadata; return metadata; @@ -294,6 +298,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc } } + + RenameExistingNfo(GetEpisodeMetadataFilename(episodeFile.RelativePath)); + return new MetadataFileResult(GetEpisodeMetadataFilename(episodeFile.RelativePath), xmlResult.Trim(Environment.NewLine.ToCharArray())); } @@ -373,6 +380,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc } } + private void RenameExistingNfo(string nfoFilePath) + { + + } + private string GetEpisodeMetadataFilename(string episodeFilePath) { return Path.ChangeExtension(episodeFilePath, "nfo"); diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcNfoDetector.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcNfoDetector.cs new file mode 100644 index 000000000..405d0e7a3 --- /dev/null +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcNfoDetector.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using NzbDrone.Common.Disk; + +namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc +{ + public interface IDetectXbmcNfo + { + bool IsXbmcNfoFile(string path); + } + + public class XbmcNfoDetector : IDetectXbmcNfo + { + private readonly IDiskProvider _diskProvider; + + private readonly Regex _regex = new Regex("<(movie|tvshow|episodedetails|artist|album|musicvideo)>", RegexOptions.Compiled); + + public XbmcNfoDetector(IDiskProvider diskProvider) + { + _diskProvider = diskProvider; + } + + public bool IsXbmcNfoFile(string path) + { + // Lets make sure we're not reading huge files. + if (_diskProvider.GetFileSize(path) > 10.Megabytes()) + { + return false; + } + + // Check if it contains some of the kodi/xbmc xml tags + var content = _diskProvider.ReadAllText(path); + + return _regex.IsMatch(content); + } + } +} diff --git a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs index 4731655e7..793662bcd 100644 --- a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs +++ b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs @@ -10,6 +10,7 @@ using NzbDrone.Common.Http; using NzbDrone.Core.Configuration; using NzbDrone.Core.Extras.Files; using NzbDrone.Core.Extras.Metadata.Files; +using NzbDrone.Core.Extras.Others; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Tv; @@ -20,6 +21,7 @@ namespace NzbDrone.Core.Extras.Metadata private readonly IMetadataFactory _metadataFactory; private readonly ICleanMetadataService _cleanMetadataService; private readonly IRecycleBinProvider _recycleBinProvider; + private readonly IOtherExtraFileRenamer _otherExtraFileRenamer; private readonly IDiskTransferService _diskTransferService; private readonly IDiskProvider _diskProvider; private readonly IHttpClient _httpClient; @@ -31,6 +33,7 @@ namespace NzbDrone.Core.Extras.Metadata IDiskProvider diskProvider, IDiskTransferService diskTransferService, IRecycleBinProvider recycleBinProvider, + IOtherExtraFileRenamer otherExtraFileRenamer, IMetadataFactory metadataFactory, ICleanMetadataService cleanMetadataService, IHttpClient httpClient, @@ -41,6 +44,7 @@ namespace NzbDrone.Core.Extras.Metadata { _metadataFactory = metadataFactory; _cleanMetadataService = cleanMetadataService; + _otherExtraFileRenamer = otherExtraFileRenamer; _recycleBinProvider = recycleBinProvider; _diskTransferService = diskTransferService; _diskProvider = diskProvider; @@ -91,7 +95,6 @@ namespace NzbDrone.Core.Extras.Metadata foreach (var consumer in _metadataFactory.Enabled()) { - files.AddIfNotNull(ProcessEpisodeMetadata(consumer, series, episodeFile, new List())); files.AddRange(ProcessEpisodeImages(consumer, series, episodeFile, new List())); } @@ -238,6 +241,8 @@ namespace NzbDrone.Core.Extras.Metadata var fullPath = Path.Combine(series.Path, episodeMetadata.RelativePath); + _otherExtraFileRenamer.RenameOtherExtraFile(series, fullPath); + var existingMetadata = GetMetadataFile(series, existingMetadataFiles, c => c.Type == MetadataType.EpisodeMetadata && c.EpisodeFileId == episodeFile.Id); @@ -292,6 +297,8 @@ namespace NzbDrone.Core.Extras.Metadata continue; } + _otherExtraFileRenamer.RenameOtherExtraFile(series, fullPath); + var metadata = GetMetadataFile(series, existingMetadataFiles, c => c.Type == MetadataType.SeriesImage && c.RelativePath == image.RelativePath) ?? new MetadataFile @@ -327,6 +334,8 @@ namespace NzbDrone.Core.Extras.Metadata continue; } + _otherExtraFileRenamer.RenameOtherExtraFile(series, fullPath); + var metadata = GetMetadataFile(series, existingMetadataFiles, c => c.Type == MetadataType.SeasonImage && c.SeasonNumber == season.SeasonNumber && c.RelativePath == image.RelativePath) ?? @@ -363,6 +372,8 @@ namespace NzbDrone.Core.Extras.Metadata continue; } + _otherExtraFileRenamer.RenameOtherExtraFile(series, fullPath); + var existingMetadata = GetMetadataFile(series, existingMetadataFiles, c => c.Type == MetadataType.EpisodeImage && c.EpisodeFileId == episodeFile.Id); diff --git a/src/NzbDrone.Core/Extras/Others/OtherExtraFileRenamer.cs b/src/NzbDrone.Core/Extras/Others/OtherExtraFileRenamer.cs new file mode 100644 index 000000000..ff4df604f --- /dev/null +++ b/src/NzbDrone.Core/Extras/Others/OtherExtraFileRenamer.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Common.Disk; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Extras.Others +{ + public interface IOtherExtraFileRenamer + { + void RenameOtherExtraFile(Series series, string path); + } + + public class OtherExtraFileRenamer : IOtherExtraFileRenamer + { + private readonly Logger _logger; + private readonly IDiskProvider _diskProvider; + private readonly IRecycleBinProvider _recycleBinProvider; + private readonly ISeriesService _seriesService; + private readonly IOtherExtraFileService _otherExtraFileService; + + public OtherExtraFileRenamer(IOtherExtraFileService otherExtraFileService, + ISeriesService seriesService, + IRecycleBinProvider recycleBinProvider, + IDiskProvider diskProvider, + Logger logger) + { + _logger = logger; + _diskProvider = diskProvider; + _recycleBinProvider = recycleBinProvider; + _seriesService = seriesService; + _otherExtraFileService = otherExtraFileService; + } + + public void RenameOtherExtraFile(Series series, string path) + { + if (!_diskProvider.FileExists(path)) + { + return; + } + + var relativePath = series.Path.GetRelativePath(path); + + var otherExtraFile = _otherExtraFileService.FindByPath(relativePath); + if (otherExtraFile != null) + { + var newPath = path + "-orig"; + + // Recycle an existing -orig file. + RemoveOtherExtraFile(series, newPath); + + // Rename the file to .*-orig + _diskProvider.MoveFile(path, newPath); + otherExtraFile.RelativePath = relativePath + "-orig"; + otherExtraFile.Extension += "-orig"; + _otherExtraFileService.Upsert(otherExtraFile); + } + } + + private void RemoveOtherExtraFile(Series series, string path) + { + if (!_diskProvider.FileExists(path)) + { + return; + } + + var relativePath = series.Path.GetRelativePath(path); + + var otherExtraFile = _otherExtraFileService.FindByPath(relativePath); + if (otherExtraFile != null) + { + var subfolder = Path.GetDirectoryName(relativePath); + _recycleBinProvider.DeleteFile(path, subfolder); + } + } + } +} diff --git a/src/NzbDrone.Core/Extras/Others/OtherExtraService.cs b/src/NzbDrone.Core/Extras/Others/OtherExtraService.cs index 18370b0fe..62d9f5129 100644 --- a/src/NzbDrone.Core/Extras/Others/OtherExtraService.cs +++ b/src/NzbDrone.Core/Extras/Others/OtherExtraService.cs @@ -65,12 +65,6 @@ namespace NzbDrone.Core.Extras.Others public override ExtraFile Import(Series series, EpisodeFile episodeFile, string path, string extension, bool readOnly) { - // If the extension is .nfo we need to change it to .nfo-orig - if (Path.GetExtension(path).Equals(".nfo", StringComparison.OrdinalIgnoreCase)) - { - extension += "-orig"; - } - var extraFile = ImportFile(series, episodeFile, path, readOnly, extension, null); _otherExtraFileService.Upsert(extraFile); diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index 7c281c65a..2a50ff2bf 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -117,7 +117,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport if (newDownload) { - _extraService.ImportExtraFiles(localEpisode, episodeFile, copyOnly); + _extraService.ImportEpisode(localEpisode, episodeFile, copyOnly); } _eventAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile, oldFiles, newDownload, downloadClientItem)); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 78f435ec3..613f76c30 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -554,6 +554,7 @@ + @@ -562,6 +563,7 @@ + From 616454edb4fa8c13bdf7da443ec9344b9cc5ece6 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Thu, 1 Mar 2018 19:21:37 +0100 Subject: [PATCH 4/4] Fixed: Preserve existing watched status in Kodi nfo files on metadata refreshes (not file upgrades). --- .../Metadata/Consumers/Xbmc/XbmcMetadata.cs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs index 096d7c889..5126fbf96 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; using NLog; +using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Core.Extras.Metadata.Files; using NzbDrone.Core.MediaCover; @@ -21,13 +22,16 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc private readonly Logger _logger; private readonly IMapCoversToLocal _mediaCoverService; private readonly IDetectXbmcNfo _detectNfo; + private readonly IDiskProvider _diskProvider; public XbmcMetadata(IDetectXbmcNfo detectNfo, + IDiskProvider diskProvider, IMapCoversToLocal mediaCoverService, Logger logger) { _logger = logger; _mediaCoverService = mediaCoverService; + _diskProvider = diskProvider; _detectNfo = detectNfo; } @@ -203,6 +207,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc _logger.Debug("Generating Episode Metadata for: {0}", Path.Combine(series.Path, episodeFile.RelativePath)); + var watched = GetExistingWatchedStatus(series, episodeFile.RelativePath); + var xmlResult = string.Empty; foreach (var episode in episodeFile.Episodes.Value) { @@ -237,7 +243,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc details.Add(new XElement("thumb", image.Url)); } - details.Add(new XElement("watched", "false")); + details.Add(new XElement("watched", watched)); if (episode.Ratings != null && episode.Ratings.Votes > 0) { @@ -298,9 +304,6 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc } } - - RenameExistingNfo(GetEpisodeMetadataFilename(episodeFile.RelativePath)); - return new MetadataFileResult(GetEpisodeMetadataFilename(episodeFile.RelativePath), xmlResult.Trim(Environment.NewLine.ToCharArray())); } @@ -380,11 +383,6 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc } } - private void RenameExistingNfo(string nfoFilePath) - { - - } - private string GetEpisodeMetadataFilename(string episodeFilePath) { return Path.ChangeExtension(episodeFilePath, "nfo"); @@ -394,5 +392,19 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc { return Path.ChangeExtension(episodeFilePath, "").Trim('.') + "-thumb.jpg"; } + + private bool GetExistingWatchedStatus(Series series, string episodeFilePath) + { + var fullPath = Path.Combine(series.Path, GetEpisodeMetadataFilename(episodeFilePath)); + + if (!_diskProvider.FileExists(fullPath)) + { + return false; + } + + var fileContent = _diskProvider.ReadAllText(fullPath); + + return Regex.IsMatch(fileContent, "true"); + } } }