Check for MusicBrainz Release Id during Scan (#227) (#277)

* Implemented functionality to find album from DB if a track has album in the MusicBrainz Release Id tag. If tag doesn't exist or album is not found, handle via normal routes.

* Added a test case

* Fixed a bad merge.

* Fixed a bug where a track with an empty Album IDv3 tag always was ignored, even if it had MusicBrainz Release Id hardcoded.

* fixup: Quick fixes to get this merged tonight due to bug in develop
This commit is contained in:
Joseph Milazzo 2018-04-06 23:52:28 -05:00 committed by Qstick
parent aaa3b5495f
commit e9097b8dc6
7 changed files with 257 additions and 31 deletions

View File

@ -0,0 +1,75 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Music;
using NzbDrone.Core.Test.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.Test.MusicTests.AlbumRepositoryTests
{
[TestFixture]
public class AlbumRepositoryFixture : DbTest<AlbumService, Album>
{
private Artist _artist;
private Album _album;
private AlbumRepository _albumRepo;
[SetUp]
public void Setup()
{
_artist = new Artist
{
Name = "Alien Ant Farm",
Monitored = true,
MBId = "this is a fake id",
Id = 1
};
_album = new Album
{
Title = "ANThology",
ForeignAlbumId = "1",
CleanTitle = "anthology",
Artist = _artist,
AlbumType = "",
Releases = new List<AlbumRelease>
{
new AlbumRelease
{
Id = "e00e40a3-5ed5-4ed3-9c22-0a8ff4119bdf"
}
}
};
_albumRepo = Mocker.Resolve<AlbumRepository>();
_albumRepo.Insert(_album);
}
[Test]
public void should_find_album_in_db_by_releaseid()
{
var id = "e00e40a3-5ed5-4ed3-9c22-0a8ff4119bdf";
var album = _albumRepo.FindAlbumByRelease(id);
album.Title.Should().Be(_album.Title);
}
[Test]
public void should_not_find_album_in_db_by_partial_releaseid()
{
var id = "e00e40a3-5ed5-4ed3-9c22";
var album = _albumRepo.FindAlbumByRelease(id);
album.Should().BeNull();
}
}
}

View File

@ -299,6 +299,7 @@
<Compile Include="MusicTests\AddAlbumFixture.cs" />
<Compile Include="MusicTests\AddArtistFixture.cs" />
<Compile Include="MusicTests\AlbumMonitoredServiceTests\AlbumMonitoredServiceFixture.cs" />
<Compile Include="MusicTests\AlbumRepositoryTests\AlbumRepositoryFixture.cs" />
<Compile Include="MusicTests\ArtistRepositoryTests\ArtistRepositoryFixture.cs" />
<Compile Include="MusicTests\ArtistServiceTests\AddArtistFixture.cs" />
<Compile Include="MusicTests\ArtistServiceTests\UpdateMultipleArtistFixture.cs" />
@ -309,6 +310,7 @@
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
<Compile Include="OrganizerTests\FileNameBuilderTests\TitleTheFixture.cs" />
<Compile Include="ParserTests\MusicParserFixture.cs" />
<Compile Include="ParserTests\ParsingServiceTests\GetLocalTrackFixture.cs" />
<Compile Include="Profiles\Delay\DelayProfileServiceFixture.cs" />
<Compile Include="Profiles\Metadata\MetadataProfileServiceFixture.cs" />
<Compile Include="Profiles\Metadata\MetadataProfileRepositoryFixture.cs" />

View File

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Music;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
{
[TestFixture]
public class GetLocalTrackFixture : CoreTest<ParsingService>
{
private Artist _fakeArtist;
private Album _fakeAlbum;
private Track _fakeTrack;
private ParsedTrackInfo _parsedTrackInfo;
[SetUp]
public void Setup()
{
_fakeArtist = Builder<Artist>
.CreateNew()
.Build();
_fakeAlbum = Builder<Album>
.CreateNew()
.With(e => e.ArtistId = _fakeArtist.Id)
.With(e => e.Releases = new List<AlbumRelease>
{
new AlbumRelease
{
Id = "5ecd552b-e54b-4c37-b62c-9d6234834bad"
}
})
.Build();
_fakeTrack = Builder<Track>
.CreateNew()
.With(e => e.ArtistId = _fakeArtist.Id)
.With(e => e.AlbumId = _fakeAlbum.Id)
.With(e => e.Album = null)
.Build();
_parsedTrackInfo = Builder<ParsedTrackInfo>
.CreateNew()
.With(e => e.AlbumTitle = _fakeAlbum.Title)
.With(e => e.Title = _fakeTrack.Title)
.With(e => e.ArtistTitle = _fakeArtist.Name)
.Build();
Mocker.GetMock<IAlbumService>()
.Setup(s => s.FindByTitle(_fakeArtist.Id,_fakeAlbum.Title))
.Returns(_fakeAlbum);
Mocker.GetMock<IAlbumService>()
.Setup(s => s.FindAlbumByRelease(_fakeAlbum.Releases.First().Id))
.Returns(_fakeAlbum);
Mocker.GetMock<ITrackService>()
.Setup(s => s.FindTrackByTitle(_fakeArtist.Id, _fakeAlbum.Id, It.IsAny<int>(), _fakeTrack.Title))
.Returns(_fakeTrack);
}
private void HasAlbumTitleNoReleaseId()
{
_parsedTrackInfo.AlbumTitle = _fakeAlbum.Title;
_parsedTrackInfo.ReleaseMBId = "";
}
private void HasReleaseMbIdNoTitle()
{
_parsedTrackInfo.AlbumTitle = "";
_parsedTrackInfo.ReleaseMBId = _fakeAlbum.Releases.First().Id;
}
private void HasNoReleaseIdOrTitle()
{
_parsedTrackInfo.AlbumTitle = "";
_parsedTrackInfo.ReleaseMBId = "";
}
[Test]
public void should_find_album_with_title_no_MBID()
{
HasAlbumTitleNoReleaseId();
var localTrack = Subject.GetLocalTrack("somfile.mp3", _fakeArtist, _parsedTrackInfo);
localTrack.Artist.Id.Should().Be(_fakeArtist.Id);
localTrack.Album.Id.Should().Be(_fakeAlbum.Id);
localTrack.Tracks.First().Id.Should().Be(_fakeTrack.Id);
}
[Test]
public void should_find_album_with_release_MBID_no_title()
{
HasReleaseMbIdNoTitle();
var localTrack = Subject.GetLocalTrack("somfile.mp3", _fakeArtist, _parsedTrackInfo);
localTrack.Artist.Id.Should().Be(_fakeArtist.Id);
localTrack.Album.Id.Should().Be(_fakeAlbum.Id);
localTrack.Tracks.First().Id.Should().Be(_fakeTrack.Id);
}
[Test]
public void should_not_find_album_with_no_release_MBID_no_title()
{
HasNoReleaseIdOrTitle();
var localTrack = Subject.GetLocalTrack("somfile.mp3", _fakeArtist, _parsedTrackInfo);
ExceptionVerification.ExpectedWarns(1);
localTrack.Should().BeNull();
}
}
}

View File

@ -24,6 +24,7 @@ namespace NzbDrone.Core.Music
List<Album> ArtistAlbumsBetweenDates(Artist artist, DateTime startDate, DateTime endDate, bool includeUnmonitored);
void SetMonitoredFlat(Album album, bool monitored);
void SetMonitored(IEnumerable<int> ids, bool monitored);
Album FindAlbumByRelease(string releaseId);
}
public class AlbumRepository : BasicRepository<Album>, IAlbumRepository
@ -301,5 +302,10 @@ namespace NzbDrone.Core.Music
.Where<Artist>(artist => artist.CleanName == cleanArtistName)
.SingleOrDefault(album => album.CleanTitle == cleanTitle);
}
public Album FindAlbumByRelease(string releaseId)
{
return Query.FirstOrDefault(e => e.Releases.Any(r => r.Id == releaseId));
}
}
}

View File

@ -31,6 +31,7 @@ namespace NzbDrone.Core.Music
void UpdateMany(List<Album> albums);
void DeleteMany(List<Album> albums);
void RemoveAddOptions(Album album);
Album FindAlbumByRelease(string releaseId);
}
public class AlbumService : IAlbumService,
@ -110,6 +111,11 @@ namespace NzbDrone.Core.Music
return _albumRepository.GetAlbums(artistId).ToList();
}
public Album FindAlbumByRelease(string releaseId)
{
return _albumRepository.FindAlbumByRelease(releaseId);
}
public void RemoveAddOptions(Album album)
{
_albumRepository.SetFields(album, s => s.AddOptions);

View File

@ -206,17 +206,11 @@ namespace NzbDrone.Core.Parser
{
var fileInfo = new FileInfo(path);
var result = new ParsedTrackInfo { };
ParsedTrackInfo result;
if (MediaFiles.MediaFileExtensions.Extensions.Contains(fileInfo.Extension))
{
result = ParseAudioTags(path);
if (CommonTagRegex.IsMatch(result.AlbumTitle))
{
result.AlbumTitle = CleanAlbumTitle(result.AlbumTitle);
Logger.Debug("Cleaning Album title of common matching issues. Cleaned album title is '{0}'", result.AlbumTitle);
}
}
else
{
@ -226,7 +220,6 @@ namespace NzbDrone.Core.Parser
// TODO: Check if it is common that we might need to fallback to parser to gather details
//var result = ParseMusicTitle(fileInfo.Name);
if (result == null)
{
@ -641,6 +634,8 @@ namespace NzbDrone.Core.Parser
ArtistTitleInfo = artistTitleInfo,
Title = trackTitle
};
Logger.Trace("File Tags Parsed: Artist: {0}, Album: {1}, Disc: {2}, Track Numbers(s): {3}, TrackTitle: {4}", result.ArtistTitle, result.AlbumTitle, result.DiscNumber, trackNumber, result.Title);

View File

@ -8,6 +8,7 @@ using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Music;
using System;
using System.Drawing.Text;
namespace NzbDrone.Core.Parser
{
@ -227,14 +228,12 @@ namespace NzbDrone.Core.Parser
{
parsedTrackInfo = folderInfo.JsonClone();
parsedTrackInfo.Quality = QualityParser.ParseQuality(Path.GetFileName(filename), null, 0);
}
else
} else
{
parsedTrackInfo = Parser.ParseMusicPath(filename);
}
if (parsedTrackInfo == null || parsedTrackInfo.AlbumTitle.IsNullOrWhiteSpace())
if (parsedTrackInfo == null || (parsedTrackInfo.AlbumTitle.IsNullOrWhiteSpace()) && parsedTrackInfo.ReleaseMBId.IsNullOrWhiteSpace())
{
if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(filename)))
{
@ -244,10 +243,13 @@ namespace NzbDrone.Core.Parser
return null;
}
var tracks = GetTracks(artist, parsedTrackInfo);
//var album = _albumService.FindByTitle(artist.Id, parsedTrackInfo.AlbumTitle);
var album = tracks.FirstOrDefault()?.Album;
var album = GetAlbum(artist, parsedTrackInfo);
var tracks = new List<Track>();
if (album != null)
{
tracks = GetTracks(artist, album, parsedTrackInfo);
}
return new LocalTrack
{
Artist = artist,
@ -261,37 +263,51 @@ namespace NzbDrone.Core.Parser
};
}
private List<Track> GetTracks(Artist artist, ParsedTrackInfo parsedTrackInfo)
private Album GetAlbum(Artist artist, ParsedTrackInfo parsedTrackInfo)
{
var result = new List<Track>();
Album album = null;
if (parsedTrackInfo.AlbumTitle.IsNullOrWhiteSpace())
if (parsedTrackInfo != null && parsedTrackInfo.ReleaseMBId.IsNotNullOrWhiteSpace())
{
_logger.Debug("Album title could not be parsed for {0}", parsedTrackInfo);
return new List<Track>();
album = _albumService.FindAlbumByRelease(parsedTrackInfo.ReleaseMBId);
}
parsedTrackInfo.AlbumTitle = Parser.CleanAlbumTitle(parsedTrackInfo.AlbumTitle);
_logger.Debug("Cleaning Album title of common matching issues. Cleaned album title is '{0}'", parsedTrackInfo.AlbumTitle);
if (album == null && parsedTrackInfo.AlbumTitle.IsNullOrWhiteSpace())
{
_logger.Debug("Album title could not be parsed for {0}", parsedTrackInfo);
return null;
}
var album = _albumService.FindByTitle(artist.Id, parsedTrackInfo.AlbumTitle);
_logger.Debug("Album {0} selected for {1}", album, parsedTrackInfo);
var cleanAlbumTitle = Parser.CleanAlbumTitle(parsedTrackInfo.AlbumTitle);
_logger.Debug("Cleaning Album title of common matching issues. Cleaned album title is '{0}'", cleanAlbumTitle);
if (album == null)
{
album = _albumService.FindByTitle(artist.Id, cleanAlbumTitle);
}
if (album == null)
{
_logger.Debug("Parsed album title not found in Db for {0}", parsedTrackInfo);
return new List<Track>();
return null;
}
Track trackInfo = null;
_logger.Debug("Album {0} selected for {1}", album, parsedTrackInfo);
return album;
}
private List<Track> GetTracks(Artist artist, Album album, ParsedTrackInfo parsedTrackInfo)
{
var result = new List<Track>();
if (parsedTrackInfo.Title.IsNotNullOrWhiteSpace())
{
parsedTrackInfo.Title = Parser.CleanTrackTitle(parsedTrackInfo.Title);
_logger.Debug("Cleaning Track title of common matching issues. Cleaned track title is '{0}'", parsedTrackInfo.Title);
var cleanTrackTitle = Parser.CleanTrackTitle(parsedTrackInfo.Title);
_logger.Debug("Cleaning Track title of common matching issues. Cleaned track title is '{0}'", cleanTrackTitle);
var trackInfo = _trackService.FindTrackByTitle(artist.Id, album.Id, parsedTrackInfo.DiscNumber, cleanTrackTitle);
trackInfo = _trackService.FindTrackByTitle(artist.Id, album.Id, parsedTrackInfo.DiscNumber, parsedTrackInfo.Title);
if (trackInfo != null)
{
_logger.Debug("Track {0} selected for {1}", trackInfo, parsedTrackInfo);