New: Detect Kodi .nfo vs Scene .nfo and handle as appropriate. Rename scene .nfo to .nfo-orig only when needed.
This commit is contained in:
parent
f0eba619f3
commit
d284969379
|
@ -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<XbmcMetadata>
|
||||
{
|
||||
private Series _series;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_series = Builder<Series>.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<IDetectXbmcNfo>()
|
||||
.Setup(v => v.IsXbmcNfoFile(path))
|
||||
.Returns(true);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.EpisodeMetadata);
|
||||
|
||||
Mocker.GetMock<IDetectXbmcNfo>()
|
||||
.Verify(v => v.IsXbmcNfoFile(It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_for_scene_nfo()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.s01e01.episode.nfo");
|
||||
|
||||
Mocker.GetMock<IDetectXbmcNfo>()
|
||||
.Setup(v => v.IsXbmcNfoFile(path))
|
||||
.Returns(false);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
|
||||
Mocker.GetMock<IDetectXbmcNfo>()
|
||||
.Verify(v => v.IsXbmcNfoFile(It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -220,6 +220,7 @@
|
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Compile Include="Download\TrackedDownloads\TrackedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Extras\Metadata\Consumers\Xbmc\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="FluentTest.cs" />
|
||||
<Compile Include="Framework\CoreTest.cs" />
|
||||
<Compile Include="Framework\DbTest.cs" />
|
||||
|
@ -340,8 +341,8 @@
|
|||
<Compile Include="Messaging\Commands\CommandEqualityComparerFixture.cs" />
|
||||
<Compile Include="Messaging\Commands\CommandExecutorFixture.cs" />
|
||||
<Compile Include="Messaging\Events\EventAggregatorFixture.cs" />
|
||||
<Compile Include="Metadata\Consumers\Roksbox\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="Metadata\Consumers\Wdtv\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="Extras\Metadata\Consumers\Roksbox\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="Extras\Metadata\Consumers\Wdtv\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="NotificationTests\PlexClientServiceTest.cs" />
|
||||
<Compile Include="NotificationTests\ProwlProviderTest.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.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;
|
||||
|
|
|
@ -18,14 +18,17 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
|||
{
|
||||
public class XbmcMetadata : MetadataBase<XbmcMetadataSettings>
|
||||
{
|
||||
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(@"^(?<type>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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<MetadataFile>()));
|
||||
files.AddRange(ProcessEpisodeImages(consumer, series, episodeFile, new List<MetadataFile>()));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -554,6 +554,7 @@
|
|||
<Compile Include="Extras\IImportExistingExtraFiles.cs" />
|
||||
<Compile Include="Extras\ImportExistingExtraFileFilterResult.cs" />
|
||||
<Compile Include="Extras\ImportExistingExtraFilesBase.cs" />
|
||||
<Compile Include="Extras\Metadata\Consumers\Xbmc\XbmcNfoDetector.cs" />
|
||||
<Compile Include="Extras\Metadata\Files\MetadataFile.cs" />
|
||||
<Compile Include="Extras\Metadata\Files\MetadataFileRepository.cs" />
|
||||
<Compile Include="Extras\Metadata\Files\MetadataFileService.cs" />
|
||||
|
@ -562,6 +563,7 @@
|
|||
<Compile Include="Extras\Others\OtherExtraFileService.cs" />
|
||||
<Compile Include="Extras\Others\OtherExtraFile.cs" />
|
||||
<Compile Include="Extras\Others\OtherExtraService.cs" />
|
||||
<Compile Include="Extras\Others\OtherExtraFileRenamer.cs" />
|
||||
<Compile Include="Extras\Subtitles\ExistingSubtitleImporter.cs" />
|
||||
<Compile Include="Extras\Subtitles\SubtitleFileRepository.cs" />
|
||||
<Compile Include="Extras\Subtitles\SubtitleFileService.cs" />
|
||||
|
|
Loading…
Reference in New Issue