mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-19 21:13:28 -07:00
New: Check whether an existing trackfile was deleted before grabbing an upgrade, to avoid timing issues in combination with Ignore Deleted Tracks.
Sonarr fa006d85f
This commit is contained in:
parent
77aa34c340
commit
64d9457322
33 changed files with 334 additions and 29 deletions
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
@ -28,6 +28,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
private Mock<IDecisionEngineSpecification> _fail2;
|
private Mock<IDecisionEngineSpecification> _fail2;
|
||||||
private Mock<IDecisionEngineSpecification> _fail3;
|
private Mock<IDecisionEngineSpecification> _fail3;
|
||||||
|
|
||||||
|
private Mock<IDecisionEngineSpecification> _failDelayed1;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
|
@ -39,6 +41,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_fail2 = new Mock<IDecisionEngineSpecification>();
|
_fail2 = new Mock<IDecisionEngineSpecification>();
|
||||||
_fail3 = new Mock<IDecisionEngineSpecification>();
|
_fail3 = new Mock<IDecisionEngineSpecification>();
|
||||||
|
|
||||||
|
_failDelayed1 = new Mock<IDecisionEngineSpecification>();
|
||||||
|
|
||||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
||||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
||||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Accept);
|
||||||
|
@ -47,6 +51,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail2"));
|
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail2"));
|
||||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail3"));
|
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("fail3"));
|
||||||
|
|
||||||
|
_failDelayed1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteAlbum>(), null)).Returns(Decision.Reject("failDelayed1"));
|
||||||
|
_failDelayed1.SetupGet(c => c.Priority).Returns(SpecificationPriority.Disk);
|
||||||
|
|
||||||
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT" } };
|
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Coldplay-A Head Full Of Dreams-CD-FLAC-2015-PERFECT" } };
|
||||||
_remoteAlbum = new RemoteAlbum {
|
_remoteAlbum = new RemoteAlbum {
|
||||||
Artist = new Artist(),
|
Artist = new Artist(),
|
||||||
|
@ -78,6 +85,25 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_pass3.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
|
_pass3.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_call_delayed_specifications_if_non_delayed_passed()
|
||||||
|
{
|
||||||
|
GivenSpecifications(_pass1, _failDelayed1);
|
||||||
|
|
||||||
|
Subject.GetRssDecision(_reports).ToList();
|
||||||
|
_failDelayed1.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_call_delayed_specifications_if_non_delayed_failed()
|
||||||
|
{
|
||||||
|
GivenSpecifications(_fail1, _failDelayed1);
|
||||||
|
|
||||||
|
Subject.GetRssDecision(_reports).ToList();
|
||||||
|
|
||||||
|
_failDelayed1.Verify(c => c.IsSatisfiedBy(_remoteAlbum, null), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_rejected_if_single_specs_fail()
|
public void should_return_rejected_if_single_specs_fail()
|
||||||
{
|
{
|
||||||
|
@ -287,4 +313,4 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
ExceptionVerification.ExpectedErrors(1);
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
|
||||||
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Music;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using Moq;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class DeletedTrackFileSpecificationFixture : CoreTest<DeletedTrackFileSpecification>
|
||||||
|
{
|
||||||
|
private RemoteAlbum _parseResultMulti;
|
||||||
|
private RemoteAlbum _parseResultSingle;
|
||||||
|
private TrackFile _firstFile;
|
||||||
|
private TrackFile _secondFile;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_firstFile =
|
||||||
|
new TrackFile{
|
||||||
|
Id = 1,
|
||||||
|
RelativePath = "My.Artist.S01E01.mp3",
|
||||||
|
Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)),
|
||||||
|
DateAdded = DateTime.Now,
|
||||||
|
AlbumId = 1
|
||||||
|
|
||||||
|
};
|
||||||
|
_secondFile =
|
||||||
|
new TrackFile{
|
||||||
|
Id = 2,
|
||||||
|
RelativePath = "My.Artist.S01E02.mp3",
|
||||||
|
Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)),
|
||||||
|
DateAdded = DateTime.Now,
|
||||||
|
AlbumId = 2
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var singleAlbumList = new List<Album> { new Album { Id = 1 } };
|
||||||
|
var doubleAlbumList = new List<Album> {
|
||||||
|
new Album { Id = 1 },
|
||||||
|
new Album { Id = 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var firstTrack = new Track { TrackFile = _firstFile, TrackFileId = 1, AlbumId = 1 };
|
||||||
|
var secondTrack = new Track { TrackFile = _secondFile, TrackFileId = 2, AlbumId = 2 };
|
||||||
|
|
||||||
|
var fakeArtist = Builder<Artist>.CreateNew()
|
||||||
|
.With(c => c.Profile = new Profile { Cutoff = Quality.FLAC })
|
||||||
|
.With(c => c.Path = @"C:\Music\My.Artist".AsOsAgnostic())
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_parseResultMulti = new RemoteAlbum
|
||||||
|
{
|
||||||
|
Artist = fakeArtist,
|
||||||
|
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||||
|
Albums = doubleAlbumList
|
||||||
|
};
|
||||||
|
|
||||||
|
_parseResultSingle = new RemoteAlbum
|
||||||
|
{
|
||||||
|
Artist = fakeArtist,
|
||||||
|
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||||
|
Albums = singleAlbumList
|
||||||
|
};
|
||||||
|
|
||||||
|
GivenUnmonitorDeletedTracks(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenUnmonitorDeletedTracks(bool enabled)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IConfigService>()
|
||||||
|
.SetupGet(v => v.AutoUnmonitorPreviouslyDownloadedTracks)
|
||||||
|
.Returns(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupMediaFile(List<TrackFile> files)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IMediaFileService>()
|
||||||
|
.Setup(v => v.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||||
|
.Returns(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WithExistingFile(TrackFile trackFile)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(@"C:\Music\My.Artist".AsOsAgnostic(), trackFile.RelativePath);
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(v => v.FileExists(path))
|
||||||
|
.Returns(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_unmonitor_deleted_tracks_is_off()
|
||||||
|
{
|
||||||
|
GivenUnmonitorDeletedTracks(false);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_searching()
|
||||||
|
{
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, new ArtistSearchCriteria()).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_file_exists()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
SetupMediaFile(new List<TrackFile> { _firstFile });
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_file_is_missing()
|
||||||
|
{
|
||||||
|
SetupMediaFile(new List<TrackFile> { _firstFile });
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_both_of_multiple_episode_exist()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
WithExistingFile(_secondFile);
|
||||||
|
SetupMediaFile(new List<TrackFile> { _firstFile, _secondFile });
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_one_of_multiple_episode_is_missing()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
SetupMediaFile(new List<TrackFile> { _firstFile, _secondFile });
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,6 +152,7 @@
|
||||||
<Compile Include="DecisionEngineTests\MinimumAgeSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\MinimumAgeSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
|
||||||
|
<Compile Include="DecisionEngineTests\RssSync\DeletedTrackFileSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\Search\ArtistSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\Search\ArtistSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -111,9 +111,16 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
private DownloadDecision GetDecisionForReport(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria = null)
|
private DownloadDecision GetDecisionForReport(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteAlbum, searchCriteria))
|
var reasons = new Rejection[0];
|
||||||
.Where(c => c != null);
|
|
||||||
|
|
||||||
|
foreach (var specifications in _specifications.GroupBy(v => v.Priority).OrderBy(v => v.Key))
|
||||||
|
{
|
||||||
|
reasons = specifications.Select(c => EvaluateSpec(c, remoteAlbum, searchCriteria))
|
||||||
|
.Where(c => c != null)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (reasons.Any()) break;
|
||||||
|
}
|
||||||
return new DownloadDecision(remoteAlbum, reasons.ToArray());
|
return new DownloadDecision(remoteAlbum, reasons.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
@ -7,6 +7,8 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
RejectionType Type { get; }
|
RejectionType Type { get; }
|
||||||
|
|
||||||
|
SpecificationPriority Priority { get; }
|
||||||
|
|
||||||
Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria);
|
Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/NzbDrone.Core/DecisionEngine/SpecificationPriority.cs
Normal file
10
src/NzbDrone.Core/DecisionEngine/SpecificationPriority.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
{
|
||||||
|
public enum SpecificationPriority
|
||||||
|
{
|
||||||
|
Default = 0,
|
||||||
|
Parsing = 0,
|
||||||
|
Database = 0,
|
||||||
|
Disk = 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
@ -19,6 +19,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Blacklisting;
|
using NzbDrone.Core.Blacklisting;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_mediaFileService = mediaFileService;
|
_mediaFileService = mediaFileService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Temporary;
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -9,6 +9,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public NotSampleSpecification(Logger logger)
|
public NotSampleSpecification(Logger logger)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -18,6 +18,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -20,6 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Temporary;
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Music;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
|
{
|
||||||
|
public class DeletedTrackFileSpecification : IDecisionEngineSpecification
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
private readonly IMediaFileService _albumService;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public DeletedTrackFileSpecification(IDiskProvider diskProvider,
|
||||||
|
IConfigService configService,
|
||||||
|
IMediaFileService albumService,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_configService = configService;
|
||||||
|
_albumService = albumService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Disk;
|
||||||
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
if (!_configService.AutoUnmonitorPreviouslyDownloadedTracks)
|
||||||
|
{
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchCriteria != null)
|
||||||
|
{
|
||||||
|
_logger.Debug("Skipping deleted trackfile check during search");
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
var missingTrackFiles = subject.Albums
|
||||||
|
.SelectMany(v => _albumService.GetFilesByAlbum(v.ArtistId, v.Id))
|
||||||
|
.DistinctBy(v => v.Id)
|
||||||
|
.Where(v => IsTrackFileMissing(subject.Artist, v))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
if (missingTrackFiles.Any())
|
||||||
|
{
|
||||||
|
foreach (var missingTrackFile in missingTrackFiles)
|
||||||
|
{
|
||||||
|
_logger.Trace("Track file {0} is missing from disk.", missingTrackFile.RelativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Files for this album exist in the database but not on disk, will be unmonitored on next diskscan. skipping.");
|
||||||
|
return Decision.Reject("Artist is not monitored");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTrackFileMissing(Artist artist, TrackFile trackFile)
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(artist.Path, trackFile.RelativePath);
|
||||||
|
|
||||||
|
return !_diskProvider.FileExists(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
||||||
|
@ -33,4 +34,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
@ -23,4 +24,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
// TODO Rework for Daily Audio/Podcasts
|
// TODO Rework for Daily Audio/Podcasts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
@ -21,4 +22,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
@ -15,6 +15,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
||||||
|
@ -45,4 +46,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteAlbum remoteAlbum, SearchCriteriaBase searchCriteria)
|
||||||
|
@ -33,4 +34,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|
|
@ -328,6 +328,7 @@
|
||||||
<Compile Include="DecisionEngine\RejectionType.cs" />
|
<Compile Include="DecisionEngine\RejectionType.cs" />
|
||||||
<Compile Include="DecisionEngine\SameEpisodesSpecification.cs" />
|
<Compile Include="DecisionEngine\SameEpisodesSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\SameTracksSpecification.cs" />
|
<Compile Include="DecisionEngine\SameTracksSpecification.cs" />
|
||||||
|
<Compile Include="DecisionEngine\SpecificationPriority.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\AcceptableSizeSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\AcceptableSizeSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\BlacklistSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\BlacklistSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\DiscographySpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\DiscographySpecification.cs" />
|
||||||
|
@ -341,6 +342,7 @@
|
||||||
<Compile Include="DecisionEngine\Specifications\MinimumAgeSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\MinimumAgeSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RetentionSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RetentionSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RssSync\DelaySpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RssSync\DelaySpecification.cs" />
|
||||||
|
<Compile Include="DecisionEngine\Specifications\RssSync\DeletedTrackFileSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RssSync\HistorySpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RssSync\HistorySpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RssSync\MonitoredAlbumSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RssSync\MonitoredAlbumSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RssSync\ProperSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RssSync\ProperSpecification.cs" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue