Fixed: Grab discography during artist search (#208)

Closes #184
This commit is contained in:
Qstick 2018-02-10 05:03:12 +01:00 committed by GitHub
parent c105c9a65e
commit 37d1ed4a48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 249 additions and 43 deletions

View File

@ -25,7 +25,7 @@ namespace Lidarr.Api.V1.Indexers
public string SubGroup { get; set; }
public string ReleaseHash { get; set; }
public string Title { get; set; }
public bool FullSeason { get; set; }
public bool Discography { get; set; }
public bool SceneSource { get; set; }
public Language Language { get; set; }
public string AirDate { get; set; }
@ -84,7 +84,7 @@ namespace Lidarr.Api.V1.Indexers
Language = parsedAlbumInfo.Language,
ArtistName = parsedAlbumInfo.ArtistName,
AlbumTitle = parsedAlbumInfo.AlbumTitle,
Discography = parsedAlbumInfo.Discography,
Approved = model.Approved,
TemporarilyRejected = model.TemporarilyRejected,
Rejected = model.Rejected,

View File

@ -0,0 +1,74 @@
using System;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using FizzWare.NBuilder;
using System.Linq;
using FluentAssertions;
using NzbDrone.Core.Music;
using Moq;
using System.Collections.Generic;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class DiscographySpecificationFixture : CoreTest<DiscographySpecification>
{
private RemoteAlbum _remoteAlbum;
[SetUp]
public void Setup()
{
var artist = Builder<Artist>.CreateNew().With(s => s.Id = 1234).Build();
_remoteAlbum = new RemoteAlbum
{
ParsedAlbumInfo = new ParsedAlbumInfo
{
Discography = true
},
Albums = Builder<Album>.CreateListOfSize(3)
.All()
.With(e => e.ReleaseDate = DateTime.UtcNow.AddDays(-8))
.With(s => s.ArtistId = artist.Id)
.BuildList(),
Artist = artist,
Release = new ReleaseInfo
{
Title = "Artist.Discography.1978.2005.FLAC-RlsGrp"
}
};
Mocker.GetMock<IAlbumService>().Setup(s => s.AlbumsBetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), false))
.Returns(new List<Album>());
}
[Test]
public void should_return_true_if_is_not_a_discography()
{
_remoteAlbum.ParsedAlbumInfo.Discography = false;
_remoteAlbum.Albums.Last().ReleaseDate = DateTime.UtcNow.AddDays(+2);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_all_albums_have_released()
{
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_one_album_has_not_released()
{
_remoteAlbum.Albums.Last().ReleaseDate = DateTime.UtcNow.AddDays(+2);
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_an_album_does_not_have_an_release_date()
{
_remoteAlbum.Albums.Last().ReleaseDate = null;
Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse();
}
}
}

View File

@ -124,5 +124,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
WithFirstAlbumUnmonitored();
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultSingle, new AlbumSearchCriteria{ MonitoredEpisodesOnly = true}).Accepted.Should().BeFalse();
}
[Test]
public void should_return_false_if_all_albums_are_not_monitored_for_discography_pack_release()
{
WithSecondAlbumUnmonitored();
_parseResultMulti.ParsedAlbumInfo = new ParsedAlbumInfo()
{
Discography = true
};
_monitoredAlbumSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
}
}
}

View File

@ -137,7 +137,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_not_throw_if_no_episodes_are_found()
public void should_not_throw_if_no_albums_are_found()
{
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), Language.English, size: 500.Megabytes());
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), Language.English, size: 500.Megabytes());
@ -183,6 +183,38 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
qualifiedReports.First().RemoteAlbum.Release.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
}
[Test]
public void should_prefer_discography_pack_above_single_album()
{
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1), GivenAlbum(2) }, new QualityModel(Quality.FLAC), Language.English);
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.FLAC), Language.English);
remoteAlbum1.ParsedAlbumInfo.Discography = true;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteAlbum.ParsedAlbumInfo.Discography.Should().BeTrue();
}
[Test]
public void should_prefer_quality_over_discography_pack()
{
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1), GivenAlbum(2) }, new QualityModel(Quality.MP3_320), Language.English);
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.FLAC), Language.English);
remoteAlbum1.ParsedAlbumInfo.Discography = true;
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteAlbum1));
decisions.Add(new DownloadDecision(remoteAlbum2));
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
qualifiedReports.First().RemoteAlbum.ParsedAlbumInfo.Discography.Should().BeFalse();
}
[Test]
public void should_prefer_single_album_over_multi_album()
{

View File

@ -129,6 +129,7 @@
<Compile Include="Datastore\SqliteSchemaDumperTests\SqliteSchemaDumperFixture.cs" />
<Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\BlockedIndexerSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\DiscographySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\MaximumSizeSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\ProtocolSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\CutoffSpecificationFixture.cs" />

View File

@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Ricardo Arjona - APNEA (Single 2014) (320 kbps)", "Ricardo Arjona", "APNEA")]
[TestCase("Kehlani - SweetSexySavage (Deluxe Edition) (2017) 320", "Kehlani", "SweetSexySavage")]
[TestCase("Anderson Paak - Malibu (320)(2016)", "Anderson Paak", "Malibu")]
[TestCase("Caetano Veloso Discografia Completa MP3 @256", "Caetano Veloso", "", true)]
[TestCase("Caetano Veloso Discografia Completa MP3 @256", "Caetano Veloso", "Discography", true)]
[TestCase("Little Mix - Salute [Deluxe Edition] [2013] [M4A-256]-V3nom [GLT", "Little Mix", "Salute")]
[TestCase("Ricky Martin - A Quien Quiera Escuchar (2015) 256 kbps [GloDLS]", "Ricky Martin", "A Quien Quiera Escuchar")]
[TestCase("Jake Bugg - Jake Bugg (Album) [2012] {MP3 256 kbps}", "Jake Bugg", "Jake Bugg")]
@ -113,7 +113,9 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("New.Edition-One.Love-CD-FLAC-2017-MrFlac", "New Edition", "One Love")]
[TestCase("David_Gray-The_Best_of_David_Gray-(Deluxe_Edition)-2CD-2016-MTD", "David Gray", "The Best of David Gray")]
[TestCase("Shinedown-Us and Them-NMR-2005-NMR", "Shinedown", "Us and Them")]
[TestCase("Captain-Discography_1998_-_2001-CD-FLAC-2007-UTP", "Captain", "", true)]
[TestCase("Led Zeppelin - Studio Discography 1969-1982 (10 albums)(flac)", "Led Zeppelin", "Discography", true)]
[TestCase("Minor Threat - Complete Discography [1989] [Anthology]", "Minor Threat", "Discography", true)]
[TestCase("Captain-Discography_1998_-_2001-CD-FLAC-2007-UTP", "Captain", "Discography", true)]
[TestCase("Coolio - Gangsta's Paradise (1995) (FLAC Lossless)", "Coolio", "Gangsta's Paradise")]
// ruTracker
[TestCase("(Eclectic Progressive Rock) [CD] Peter Hammill - From The Trees - 2017, FLAC (tracks + .cue), lossless", "Peter Hammill","From The Trees")]
@ -121,10 +123,10 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("(Zeuhl / Progressive Rock) [WEB] Dai Kaht - Dai Kaht - 2017, FLAC (tracks), lossless", "Dai Kaht", "Dai Kaht")]
//[TestCase("(Industrial Folk) Bumblebee(Shmely, AntiVirus) - Discography, 23 albums - 1998-2011, FLAC(image + .cue), lossless")]
//[TestCase("(Heavy Metal) Sergey Mavrin(Mavrik) - Discography(14 CD) [1998-2010], FLAC(image + .cue), lossless")]
[TestCase("(Heavy Metal) [CD] Black Obelisk - Discography - 1991-2015 (36 releases, 32 CDs), FLAC(image + .cue), lossless", "Black Obelisk", "", true)]
[TestCase("(Heavy Metal) [CD] Black Obelisk - Discography - 1991-2015 (36 releases, 32 CDs), FLAC(image + .cue), lossless", "Black Obelisk", "Discography", true)]
//[TestCase("(R'n'B / Soul) Moyton - One of the Sta(2014) + Ocean(2014), MP3, 320 kbps", "Moyton", "")]
[TestCase("(Heavy Metal) Aria - Discography(46 CD) [1985 - 2015], FLAC(image + .cue), lossless", "Aria", "", true)]
[TestCase("(Heavy Metal) [CD] Forces United - Discography(6 CDs), 2014-2016, FLAC(image + .cue), lossless", "Forces United", "", true)]
[TestCase("(Heavy Metal) Aria - Discography(46 CD) [1985 - 2015], FLAC(image + .cue), lossless", "Aria", "Discography", true)]
[TestCase("(Heavy Metal) [CD] Forces United - Discography(6 CDs), 2014-2016, FLAC(image + .cue), lossless", "Forces United", "Discography", true)]
public void should_parse_artist_name_and_album_title(string postTitle, string name, string title, bool discography = false)
{
@ -146,6 +148,20 @@ namespace NzbDrone.Core.Test.ParserTests
parseResult.AlbumTitle.ToLowerInvariant().Should().Be("black sabbath");
}
[TestCase("Captain-Discography_1998_-_2001-CD-FLAC-2007-UTP", 1998, 2001)]
[TestCase("(Heavy Metal) Aria - Discography(46 CD) [1985 - 2015]", 1985, 2015)]
[TestCase("Led Zeppelin - Studio Discography 1969-1982 (10 albums)(flac)", 1969, 1982)]
[TestCase("Minor Threat - Complete Discography [1989] [Anthology]", 0, 1989)]
[TestCase("Caetano Veloso Discografia Completa MP3 @256", 0, 0)]
public void should_parse_year_or_year_range_from_discography(string releaseTitle, int startyear,
int endyear)
{
var parseResult = Parser.Parser.ParseAlbumTitle(releaseTitle);
parseResult.Discography.Should().BeTrue();
parseResult.DiscographyStart.Should().Be(startyear);
parseResult.DiscographyEnd.Should().Be(endyear);
}
[Test]
public void should_not_parse_artist_name_and_album_title_by_incorrect_search_criteria()
{

View File

@ -80,6 +80,14 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareAlbumCount(DownloadDecision x, DownloadDecision y)
{
var discographyCompare = CompareBy(x.RemoteAlbum, y.RemoteAlbum,
remoteAlbum => remoteAlbum.ParsedAlbumInfo.Discography);
if (discographyCompare != 0)
{
return discographyCompare;
}
return CompareByReverse(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Albums.Count);
}

View File

@ -2,8 +2,8 @@ using System;
using NLog;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Common.Extensions;
using System.Linq;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.DecisionEngine.Specifications
{
@ -21,7 +21,18 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
{
throw new NotImplementedException();
if (subject.ParsedAlbumInfo.Discography)
{
_logger.Debug("Checking if all albums in discography release have released. {0}", subject.Release.Title);
if (subject.Albums.Any(e => !e.ReleaseDate.HasValue || e.ReleaseDate.Value.After(DateTime.UtcNow)))
{
_logger.Debug("Discography release {0} rejected. All albums haven't released yet.", subject.Release.Title);
return Decision.Reject("Discography release rejected. All albums haven't released yet.");
}
}
return Decision.Accept();
}
}
}

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Qualities;
using Marr.Data.QGen;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.Music
@ -22,6 +21,7 @@ namespace NzbDrone.Core.Music
PagingSpec<Album> AlbumsWithoutFiles(PagingSpec<Album> pagingSpec);
PagingSpec<Album> AlbumsWhereCutoffUnmet(PagingSpec<Album> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff, List<LanguagesBelowCutoff> languagesBelowCutoff);
List<Album> AlbumsBetweenDates(DateTime startDate, DateTime endDate, bool includeUnmonitored);
List<Album> ArtistAlbumsBetweenDates(Artist artist, DateTime startDate, DateTime endDate, bool includeUnmonitored);
void SetMonitoredFlat(Album album, bool monitored);
void SetMonitored(IEnumerable<int> ids, bool monitored);
}
@ -44,7 +44,7 @@ namespace NzbDrone.Core.Music
public Album FindById(string foreignAlbumId)
{
return Query.Where(s => s.ForeignAlbumId == foreignAlbumId).SingleOrDefault();
return Query.SingleOrDefault(s => s.ForeignAlbumId == foreignAlbumId);
}
public PagingSpec<Album> AlbumsWithoutFiles(PagingSpec<Album> pagingSpec)
@ -84,6 +84,23 @@ namespace NzbDrone.Core.Music
return query.ToList();
}
public List<Album> ArtistAlbumsBetweenDates(Artist artist, DateTime startDate, DateTime endDate, bool includeUnmonitored)
{
var query = Query.Join<Album, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistId == s.Id)
.Where<Album>(e => e.ReleaseDate >= startDate)
.AndWhere(e => e.ReleaseDate <= endDate)
.AndWhere(e => e.ArtistId == artist.Id);
if (!includeUnmonitored)
{
query.AndWhere(e => e.Monitored)
.AndWhere(e => e.Artist.Monitored);
}
return query.ToList();
}
private QueryBuilder<Album> GetMissingAlbumsQuery(PagingSpec<Album> pagingSpec, DateTime currentTime)
{
string sortKey;
@ -117,16 +134,6 @@ namespace NzbDrone.Core.Music
monitored, BuildReleaseDateCutoffWhereClause(currentTime), sortKey, pagingSpec.ToSortDirection(), pagingSpec.PageSize, pagingSpec.PagingOffset());
return Query.QueryText(query);
//Use Manual Query until we find a way to "NOT EXIST(SELECT 1 from Tracks WHERE [t2].trackFileId <> 0)"
//return Query.Join<Album, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistId == s.Id)
// .Where<Album>(pagingSpec.FilterExpression)
// .AndWhere(BuildReleaseDateCutoffWhereClause(currentTime))
// //.Where<Track>(t => t.TrackFileId == 0)
// .OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
// .Skip(pagingSpec.PagingOffset())
// .Take(pagingSpec.PageSize);
}
private int GetMissingAlbumsQueryCount(PagingSpec<Album> pagingSpec, DateTime currentTime)
@ -214,17 +221,17 @@ namespace NzbDrone.Core.Music
private string BuildLanguageCutoffWhereClause(List<LanguagesBelowCutoff> languagesBelowCutoff)
{
var clauses = new List<String>();
var clauses = new List<string>();
foreach (var language in languagesBelowCutoff)
{
foreach (var belowCutoff in language.LanguageIds)
{
clauses.Add(String.Format("(Artists.[LanguageProfileId] = {0} AND TrackFiles.[Language] = {1})", language.ProfileId, belowCutoff));
clauses.Add(string.Format("(Artists.[LanguageProfileId] = {0} AND TrackFiles.[Language] = {1})", language.ProfileId, belowCutoff));
}
}
return String.Format("({0})", String.Join(" OR ", clauses));
return string.Format("({0})", string.Join(" OR ", clauses));
}
private string BuildQualityCutoffWhereClause(List<QualitiesBelowCutoff> qualitiesBelowCutoff)
@ -265,8 +272,7 @@ namespace NzbDrone.Core.Music
{
cleanTitle = cleanTitle.ToLowerInvariant();
return Query.Where(s => s.CleanTitle == cleanTitle)
.SingleOrDefault();
return Query.SingleOrDefault(s => s.CleanTitle == cleanTitle);
}
public Album FindByTitle(int artistId, string title)
@ -282,13 +288,10 @@ namespace NzbDrone.Core.Music
{
var cleanArtistName = Parser.Parser.CleanArtistName(artistName);
cleanTitle = cleanTitle.ToLowerInvariant();
var query = Query.Join<Album, Artist>(JoinType.Inner, album => album.Artist, (album, artist) => album.ArtistId == artist.Id)
.Where<Artist>(artist => artist.CleanName == cleanArtistName)
.Where<Album>(album => album.CleanTitle == cleanTitle);
return Query.Join<Album, Artist>(JoinType.Inner, album => album.Artist, (album, artist) => album.ArtistId == artist.Id)
.Where<Artist>(artist => artist.CleanName == cleanArtistName)
.Where<Album>(album => album.CleanTitle == cleanTitle)
.SingleOrDefault();
.SingleOrDefault(album => album.CleanTitle == cleanTitle);
}
}
}

View File

@ -1,15 +1,10 @@
using NLog;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Music.Events;
using NzbDrone.Core.Organizer;
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Parser;
using System.Text;
using System.IO;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.Music
{
@ -31,6 +26,7 @@ namespace NzbDrone.Core.Music
void SetMonitored(IEnumerable<int> ids, bool monitored);
PagingSpec<Album> AlbumsWithoutFiles(PagingSpec<Album> pagingSpec);
List<Album> AlbumsBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
List<Album> ArtistAlbumsBetweenDates(Artist artist, DateTime start, DateTime end, bool includeUnmonitored);
void InsertMany(List<Album> albums);
void UpdateMany(List<Album> albums);
void DeleteMany(List<Album> albums);
@ -43,19 +39,16 @@ namespace NzbDrone.Core.Music
private readonly IAlbumRepository _albumRepository;
private readonly IEventAggregator _eventAggregator;
private readonly ITrackService _trackService;
private readonly IBuildFileNames _fileNameBuilder;
private readonly Logger _logger;
public AlbumService(IAlbumRepository albumRepository,
IEventAggregator eventAggregator,
ITrackService trackService,
IBuildFileNames fileNameBuilder,
Logger logger)
{
_albumRepository = albumRepository;
_eventAggregator = eventAggregator;
_trackService = trackService;
_fileNameBuilder = fileNameBuilder;
_logger = logger;
}
@ -136,6 +129,13 @@ namespace NzbDrone.Core.Music
return albums;
}
public List<Album> ArtistAlbumsBetweenDates(Artist artist, DateTime start, DateTime end, bool includeUnmonitored)
{
var albums = _albumRepository.ArtistAlbumsBetweenDates(artist, start.ToUniversalTime(), end.ToUniversalTime(), includeUnmonitored);
return albums;
}
public void InsertMany(List<Album> albums)
{
_albumRepository.InsertMany(albums);

View File

@ -16,6 +16,8 @@ namespace NzbDrone.Core.Parser.Model
public QualityModel Quality { get; set; }
public string ReleaseDate { get; set; }
public bool Discography { get; set; }
public int DiscographyStart { get; set; }
public int DiscographyEnd { get; set; }
public Language Language { get; set; }
public string ReleaseGroup { get; set; }
public string ReleaseHash { get; set; }

View File

@ -44,16 +44,28 @@ namespace NzbDrone.Core.Parser
private static readonly Regex[] ReportAlbumTitleRegex = new[]
{
//ruTracker - (Genre) [Source]? Artist - Discography
new Regex(@"^(?:\(.+?\))(?:\W*(?:\[(?<source>.+?)\]))?\W*(?<artist>.+?)(?: - )(?<discography>Discography|Discografia)",
new Regex(@"^(?:\(.+?\))(?:\W*(?:\[(?<source>.+?)\]))?\W*(?<artist>.+?)(?: - )(?<discography>Discography|Discografia).+?(?<startyear>\d{4}).+?(?<endyear>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Artist - Discography with two years
new Regex(@"^(?<artist>.+?)(?: - )(?:.+?)?(?<discography>Discography|Discografia).+?(?<startyear>\d{4}).+?(?<endyear>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Artist - Discography with end year
new Regex(@"^(?<artist>.+?)(?: - )(?:.+?)?(?<discography>Discography|Discografia).+?(?<endyear>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Artist Discography with two years
new Regex(@"^(?<artist>.+?)\W*(?<discography>Discography|Discografia).+?(?<startyear>\d{4}).+?(?<endyear>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Artist Discography with end year
new Regex(@"^(?<artist>.+?)\W*(?<discography>Discography|Discografia).+?(?<endyear>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Artist Discography
new Regex(@"^(?<artist>.+?)\W*(?<discography>Discography|Discografia)",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
new Regex(@"^(?<artist>.+?)\W*(?<discography>Discography|Discografia)",
RegexOptions.IgnoreCase | RegexOptions.Compiled),
//ruTracker - (Genre) [Source]? Artist - Album - Year
new Regex(@"^(?:\(.+?\))(?:\W*(?:\[(?<source>.+?)\]))?\W*(?<artist>.+?)(?: - )(?<album>.+?)(?: - )(?<releaseyear>\d{4})",
@ -760,7 +772,23 @@ namespace NzbDrone.Core.Parser
if (matchCollection[0].Groups["discography"].Success)
{
int discStart;
int discEnd;
int.TryParse(matchCollection[0].Groups["startyear"].Value, out discStart);
int.TryParse(matchCollection[0].Groups["endyear"].Value, out discEnd);
result.Discography = true;
if (discStart > 0 && discEnd > 0)
{
result.DiscographyStart = discStart;
result.DiscographyEnd = discEnd;
}
else if (discEnd > 0)
{
result.DiscographyEnd = discEnd;
}
result.AlbumTitle = "Discography";
}
Logger.Debug("Album Parsed. {0}", result);

View File

@ -119,6 +119,25 @@ namespace NzbDrone.Core.Parser
Album albumInfo = null;
if (parsedAlbumInfo.Discography)
{
if (parsedAlbumInfo.DiscographyStart > 0)
{
return _albumService.ArtistAlbumsBetweenDates(artist,
new DateTime(parsedAlbumInfo.DiscographyStart, 1, 1),
new DateTime(parsedAlbumInfo.DiscographyEnd, 12, 31), false);
}
if (parsedAlbumInfo.DiscographyEnd > 0)
{
return _albumService.ArtistAlbumsBetweenDates(artist,
new DateTime(1800, 1, 1),
new DateTime(parsedAlbumInfo.DiscographyEnd, 12, 31), false);
}
return _albumService.GetAlbumsByArtist(artist.Id);
}
if (searchCriteria != null)
{
albumInfo = searchCriteria.Albums.SingleOrDefault(e => e.Title == albumTitle);