mirror of https://github.com/Sonarr/Sonarr
Remove file quality matches release import spec
New: Don't reject imports when quality doesn't match release quality New: Reject grab when release was grabbed and imported already Closes #2783
This commit is contained in:
parent
b73b99df8d
commit
44048207f2
|
@ -0,0 +1,163 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AlreadyImportedSpecificationFixture : CoreTest<AlreadyImportedSpecification>
|
||||
{
|
||||
private const int FIRST_EPISODE_ID = 1;
|
||||
private const string TITLE = "Series.Title.S01E01.720p.HDTV.x264-Sonarr";
|
||||
|
||||
private Series _series;
|
||||
private QualityModel _hdtv720p;
|
||||
private QualityModel _hdtv1080p;
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
private List<History.History> _history;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var singleEpisodeList = new List<Episode>
|
||||
{
|
||||
new Episode
|
||||
{
|
||||
Id = FIRST_EPISODE_ID,
|
||||
SeasonNumber = 12,
|
||||
EpisodeNumber = 3,
|
||||
EpisodeFileId = 1
|
||||
}
|
||||
};
|
||||
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_hdtv720p = new QualityModel(Quality.HDTV720p, new Revision(version: 1));
|
||||
_hdtv1080p = new QualityModel(Quality.HDTV1080p, new Revision(version: 1));
|
||||
|
||||
_remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = _series,
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = _hdtv720p },
|
||||
Episodes = singleEpisodeList,
|
||||
Release = Builder<ReleaseInfo>.CreateNew()
|
||||
.Build()
|
||||
};
|
||||
|
||||
_history = new List<History.History>();
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.FindByEpisodeId(It.IsAny<int>()))
|
||||
.Returns(_history);
|
||||
}
|
||||
|
||||
private void GivenCdhDisabled()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
||||
.Returns(false);
|
||||
}
|
||||
|
||||
private void GivenHistoryItem(string downloadId, string sourceTitle, QualityModel quality, HistoryEventType eventType)
|
||||
{
|
||||
_history.Add(new History.History
|
||||
{
|
||||
DownloadId = downloadId,
|
||||
SourceTitle = sourceTitle,
|
||||
Quality = quality,
|
||||
Date = DateTime.UtcNow,
|
||||
EventType = eventType
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_CDH_is_disabled()
|
||||
{
|
||||
GivenCdhDisabled();
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_episode_does_not_have_a_file()
|
||||
{
|
||||
_remoteEpisode.Episodes.First().EpisodeFileId = 0;
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_episode_does_not_have_grabbed_event()
|
||||
{
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_episode_does_not_have_imported_event()
|
||||
{
|
||||
GivenHistoryItem(Guid.NewGuid().ToString().ToUpper(), TITLE, _hdtv720p, HistoryEventType.Grabbed);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_grabbed_and_imported_quality_is_the_same()
|
||||
{
|
||||
var downloadId = Guid.NewGuid().ToString().ToUpper();
|
||||
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv720p, HistoryEventType.Grabbed);
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv720p, HistoryEventType.DownloadFolderImported);
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_rejected_if_grabbed_download_id_matches_release_torrent_hash()
|
||||
{
|
||||
var downloadId = Guid.NewGuid().ToString().ToUpper();
|
||||
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv720p, HistoryEventType.Grabbed);
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv1080p, HistoryEventType.DownloadFolderImported);
|
||||
|
||||
_remoteEpisode.Release = Builder<TorrentInfo>.CreateNew()
|
||||
.With(t => t.DownloadProtocol = DownloadProtocol.Torrent)
|
||||
.With(t => t.InfoHash = downloadId)
|
||||
.Build();
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_rejected_if_release_title_matches_grabbed_event_source_title()
|
||||
{
|
||||
var downloadId = Guid.NewGuid().ToString().ToUpper();
|
||||
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv720p, HistoryEventType.Grabbed);
|
||||
GivenHistoryItem(downloadId, TITLE, _hdtv1080p, HistoryEventType.DownloadFolderImported);
|
||||
|
||||
_remoteEpisode.Release = Builder<TorrentInfo>.CreateNew()
|
||||
.With(t => t.DownloadProtocol = DownloadProtocol.Torrent)
|
||||
.With(t => t.InfoHash = downloadId)
|
||||
.Build();
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
|
@ -16,7 +16,7 @@ using NzbDrone.Core.DecisionEngine;
|
|||
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
{
|
||||
[TestFixture]
|
||||
public class HistorySpecificationFixture : CoreTest<HistorySpecification>
|
|
@ -1,123 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
[TestFixture]
|
||||
public class GrabbedReleaseQualityFixture : CoreTest<GrabbedReleaseQualitySpecification>
|
||||
{
|
||||
private LocalEpisode _localEpisode;
|
||||
private DownloadClientItem _downloadClientItem;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_localEpisode = Builder<LocalEpisode>.CreateNew()
|
||||
.With(l => l.Quality = new QualityModel(Quality.Bluray720p))
|
||||
.Build();
|
||||
|
||||
_downloadClientItem = Builder<DownloadClientItem>.CreateNew()
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void GivenHistory(List<History.History> history)
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.FindByDownloadId(It.IsAny<string>()))
|
||||
.Returns(history);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_when_downloadClientItem_is_null()
|
||||
{
|
||||
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_no_history_for_downloadId()
|
||||
{
|
||||
GivenHistory(new List<History.History>());
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_no_grabbed_history_for_downloadId()
|
||||
{
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.EventType = HistoryEventType.Unknown)
|
||||
.BuildList();
|
||||
|
||||
GivenHistory(history);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_grabbed_history_is_for_a_season_pack()
|
||||
{
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||
.With(h => h.Quality = _localEpisode.Quality)
|
||||
.With(h => h.SourceTitle = "Series.Title.S01.720p.HDTV.x264-RlsGroup")
|
||||
.BuildList();
|
||||
|
||||
GivenHistory(history);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_grabbed_history_quality_is_unknown()
|
||||
{
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||
.With(h => h.Quality = new QualityModel(Quality.Unknown))
|
||||
.BuildList();
|
||||
|
||||
GivenHistory(history);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_accepted_if_grabbed_history_quality_matches()
|
||||
{
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||
.With(h => h.Quality = _localEpisode.Quality)
|
||||
.BuildList();
|
||||
|
||||
GivenHistory(history);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_rejected_if_grabbed_history_quality_does_not_match()
|
||||
{
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||
.With(h => h.Quality = new QualityModel(Quality.HDTV720p))
|
||||
.BuildList();
|
||||
|
||||
GivenHistory(history);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -166,7 +166,8 @@
|
|||
<Compile Include="DecisionEngineTests\ProtocolSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\CutoffSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\HistorySpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\AlreadyImportedSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\RssSync\HistorySpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\QueueSpecificationFixture.cs" />
|
||||
|
@ -316,7 +317,6 @@
|
|||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\SameFileSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\GrabbedReleaseQualityFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\MatchesFolderSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotSampleSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotUnpackingSpecificationFixture.cs" />
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class AlreadyImportedSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AlreadyImportedSpecification(IHistoryService historyService,
|
||||
IConfigService configService,
|
||||
Logger logger)
|
||||
{
|
||||
_historyService = historyService;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cdhEnabled = _configService.EnableCompletedDownloadHandling;
|
||||
|
||||
if (!cdhEnabled)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check because CDH is disabled");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Performing alerady imported check on report");
|
||||
foreach (var episode in subject.Episodes)
|
||||
{
|
||||
if (!episode.HasFile)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check for episode without file");
|
||||
continue;
|
||||
}
|
||||
|
||||
var historyForEpisode = _historyService.FindByEpisodeId(episode.Id);
|
||||
var lastGrabbed = historyForEpisode.FirstOrDefault(h => h.EventType == HistoryEventType.Grabbed);
|
||||
|
||||
if (lastGrabbed == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var imported = historyForEpisode.FirstOrDefault(h =>
|
||||
h.EventType == HistoryEventType.DownloadFolderImported &&
|
||||
h.DownloadId == lastGrabbed.DownloadId);
|
||||
|
||||
if (imported == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is really only a guard against redownloading the same release over
|
||||
// and over when the grabbed and imported qualities do not match, if they do
|
||||
// match skip this check.
|
||||
if (lastGrabbed.Quality.Equals(imported.Quality))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var release = subject.Release;
|
||||
|
||||
if (release.DownloadProtocol == DownloadProtocol.Torrent)
|
||||
{
|
||||
var torrentInfo = release as TorrentInfo;
|
||||
|
||||
if (torrentInfo != null && torrentInfo.InfoHash.ToUpper() == lastGrabbed.DownloadId)
|
||||
{
|
||||
_logger.Debug("Has same torrent hash as a grabbed and imported release");
|
||||
return Decision.Reject("Has same torrent hash as a grabbed and imported release");
|
||||
}
|
||||
}
|
||||
|
||||
// Only based on title because a release with the same title on another indexer/released at
|
||||
// a different time very likely has the exact same content and we don't need to also try it.
|
||||
|
||||
if (release.Title.Equals(lastGrabbed.SourceTitle, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_logger.Debug("Has same release name as a grabbed and imported release");
|
||||
return Decision.Reject("Has same release name as a grabbed and imported release");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ namespace NzbDrone.Core.History
|
|||
{
|
||||
List<QualityModel> GetBestQualityInHistory(int episodeId);
|
||||
History MostRecentForEpisode(int episodeId);
|
||||
List<History> FindByEpisodeId(int episodeId);
|
||||
History MostRecentForDownloadId(string downloadId);
|
||||
List<History> FindByDownloadId(string downloadId);
|
||||
List<History> FindDownloadHistory(int idSeriesId, QualityModel quality);
|
||||
|
@ -43,6 +44,13 @@ namespace NzbDrone.Core.History
|
|||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<History> FindByEpisodeId(int episodeId)
|
||||
{
|
||||
return Query.Where(h => h.EpisodeId == episodeId)
|
||||
.OrderByDescending(h => h.Date)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public History MostRecentForDownloadId(string downloadId)
|
||||
{
|
||||
return Query.Where(h => h.DownloadId == downloadId)
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace NzbDrone.Core.History
|
|||
QualityModel GetBestQualityInHistory(Profile profile, int episodeId);
|
||||
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
||||
History MostRecentForEpisode(int episodeId);
|
||||
List<History> FindByEpisodeId(int episodeId);
|
||||
History MostRecentForDownloadId(string downloadId);
|
||||
History Get(int historyId);
|
||||
List<History> Find(string downloadId, HistoryEventType eventType);
|
||||
|
@ -55,6 +56,11 @@ namespace NzbDrone.Core.History
|
|||
return _historyRepository.MostRecentForEpisode(episodeId);
|
||||
}
|
||||
|
||||
public List<History> FindByEpisodeId(int episodeId)
|
||||
{
|
||||
return _historyRepository.FindByEpisodeId(episodeId);
|
||||
}
|
||||
|
||||
public History MostRecentForDownloadId(string downloadId)
|
||||
{
|
||||
return _historyRepository.MostRecentForDownloadId(downloadId);
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
public class GrabbedReleaseQualitySpecification : IImportDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public GrabbedReleaseQualitySpecification(IHistoryService historyService, Logger logger)
|
||||
{
|
||||
_historyService = historyService;
|
||||
_logger = logger;
|
||||
}
|
||||
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
_logger.Debug("No download client item provided, skipping.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var grabbedHistory = _historyService.FindByDownloadId(downloadClientItem.DownloadId)
|
||||
.Where(h => h.EventType == HistoryEventType.Grabbed)
|
||||
.ToList();
|
||||
|
||||
if (grabbedHistory.Empty())
|
||||
{
|
||||
_logger.Debug("No grabbed history for this download client item");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var parsedReleaseName = Parser.Parser.ParseTitle(grabbedHistory.First().SourceTitle);
|
||||
|
||||
if (parsedReleaseName != null && parsedReleaseName.FullSeason)
|
||||
{
|
||||
_logger.Debug("File is part of a season pack, skipping.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
foreach (var item in grabbedHistory)
|
||||
{
|
||||
if (item.Quality.Quality != Quality.Unknown && item.Quality != localEpisode.Quality)
|
||||
{
|
||||
_logger.Debug("Quality for grabbed release ({0}) does not match the quality of the file ({1})", item.Quality, localEpisode.Quality);
|
||||
return Decision.Reject("File quality does not match quality of the grabbed release");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -143,6 +143,7 @@
|
|||
<Compile Include="Configuration\IConfigService.cs" />
|
||||
<Compile Include="Configuration\InvalidConfigFileException.cs" />
|
||||
<Compile Include="Configuration\ResetApiKeyCommand.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\AlreadyImportedSpecification.cs" />
|
||||
<Compile Include="Indexers\SeedConfigProvider.cs" />
|
||||
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
|
||||
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
|
||||
|
@ -817,7 +818,6 @@
|
|||
<Compile Include="MediaFiles\EpisodeImport\Specifications\EpisodeTitleSpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\SameFileSpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\GrabbedReleaseQualitySpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\MatchesFolderSpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotSampleSpecification.cs" />
|
||||
|
|
Loading…
Reference in New Issue