mirror of
https://github.com/fergalmoran/Readarr.git
synced 2026-01-24 17:44:24 +00:00
Fixed: Split concatenated authors when calculating match
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.MediaFiles.BookImport.Identification;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles.BookImport.Identification
|
||||
{
|
||||
[TestFixture]
|
||||
public class DistanceCalculatorFixture : TestBase
|
||||
{
|
||||
[Test]
|
||||
public void should_reverse_single_reversed_author()
|
||||
{
|
||||
var input = new List<string> { "Last, First" };
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().Contain("First Last");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_reverse_two_reversed_author()
|
||||
{
|
||||
var input = new List<string>
|
||||
{
|
||||
"Last, First",
|
||||
"Last2, First2"
|
||||
};
|
||||
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().HaveCount(4);
|
||||
authors.Should().Contain("First Last");
|
||||
authors.Should().Contain("First2 Last2");
|
||||
authors.Should().Contain("Last, First");
|
||||
authors.Should().Contain("Last2, First2");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_reverse_single_author()
|
||||
{
|
||||
var input = new List<string> { "First Last" };
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().HaveCount(1);
|
||||
authors.Should().Contain("First Last");
|
||||
}
|
||||
|
||||
[TestCase("First1 Last1, First2 Last2", "First1 Last1", "First2 Last2")]
|
||||
[TestCase("First1 Last1; First2 Last2", "First1 Last1", "First2 Last2")]
|
||||
[TestCase("First1 Last1 & First2 Last2", "First1 Last1", "First2 Last2")]
|
||||
[TestCase("First1 Last1 / First2 Last2", "First1 Last1", "First2 Last2")]
|
||||
[TestCase("First1 Last1 and First2 Last2", "First1 Last1", "First2 Last2")]
|
||||
public void should_split_concatenated_author(string inputString, string first, string second)
|
||||
{
|
||||
var input = new List<string> { inputString };
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().Contain(inputString);
|
||||
authors.Should().Contain(first);
|
||||
authors.Should().Contain(second);
|
||||
authors.Should().HaveCount(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_split_concatenated_with_trailing_and()
|
||||
{
|
||||
var inputString = "First Last, First2 Last2 & First3 Last3";
|
||||
var input = new List<string> { inputString };
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().Contain(inputString);
|
||||
authors.Should().Contain("First Last");
|
||||
authors.Should().Contain("First2 Last2");
|
||||
authors.Should().Contain("First3 Last3");
|
||||
authors.Should().HaveCount(4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_split_if_multiple_input()
|
||||
{
|
||||
var input = new List<string>
|
||||
{
|
||||
"First Last",
|
||||
"Second Third, Fourth Fifth"
|
||||
};
|
||||
|
||||
var authors = DistanceCalculator.GetAuthorVariants(input);
|
||||
|
||||
authors.Should().HaveCount(2);
|
||||
authors.Should().Contain("First Last");
|
||||
authors.Should().Contain("Second Third, Fourth Fifth");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
authors.AddRange(tag.PerformersSort);
|
||||
}
|
||||
|
||||
BookAuthors = authors.ToArray();
|
||||
BookAuthors = authors.Distinct().ToArray();
|
||||
Track = tag.Track;
|
||||
TrackCount = tag.TrackCount;
|
||||
Book = tag.Album ?? tag.AlbumSort;
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
|
||||
{
|
||||
// Sort by most voted so less likely to swap to a random release
|
||||
return GetDbCandidatesByEdition(_editionService.GetEditionsByBook(book.Id)
|
||||
.OrderByDescending(x => x.Ratings.Votes)
|
||||
.OrderByDescending(x => x.Ratings.Popularity)
|
||||
.ToList(), includeExisting);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,9 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
|
||||
var authorTags = localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.Authors) ?? new List<string>();
|
||||
if (authorTags.Any())
|
||||
{
|
||||
foreach (var authorTag in authorTags)
|
||||
var variants = DistanceCalculator.GetAuthorVariants(authorTags.Where(x => x.IsNotNullOrWhiteSpace()).ToList());
|
||||
|
||||
foreach (var authorTag in variants)
|
||||
{
|
||||
if (authorTag.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
|
||||
@@ -30,15 +30,7 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
|
||||
.First()
|
||||
.First();
|
||||
|
||||
var authors = new List<string>(fileAuthors);
|
||||
|
||||
foreach (var author in fileAuthors)
|
||||
{
|
||||
if (author.Contains(','))
|
||||
{
|
||||
authors.Add(authors[0].Split(',', 2).Select(x => x.Trim()).Reverse().ConcatToString(" "));
|
||||
}
|
||||
}
|
||||
var authors = GetAuthorVariants(fileAuthors);
|
||||
|
||||
dist.AddString("author", authors, edition.Book.Value.AuthorMetadata.Value.Name);
|
||||
Logger.Trace("author: '{0}' vs '{1}'; {2}", authors.ConcatToString("' or '"), edition.Book.Value.AuthorMetadata.Value.Name, dist.NormalizedDistance());
|
||||
@@ -115,5 +107,75 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
public static List<string> GetAuthorVariants(List<string> fileAuthors)
|
||||
{
|
||||
var authors = new List<string>(fileAuthors);
|
||||
|
||||
if (fileAuthors.Count == 1)
|
||||
{
|
||||
authors.AddRange(SplitAuthor(fileAuthors[0]));
|
||||
}
|
||||
|
||||
foreach (var author in fileAuthors)
|
||||
{
|
||||
if (author.Contains(','))
|
||||
{
|
||||
var split = author.Split(',', 2).Select(x => x.Trim());
|
||||
if (!split.First().Contains(' '))
|
||||
{
|
||||
authors.Add(split.Reverse().ConcatToString(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return authors;
|
||||
}
|
||||
|
||||
private static List<string> SplitAuthor(string input)
|
||||
{
|
||||
var seps = new[] { ';', '/' };
|
||||
foreach (var sep in seps)
|
||||
{
|
||||
if (input.Contains(sep))
|
||||
{
|
||||
return input.Split(sep).Select(x => x.Trim()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
var andSeps = new List<string> { " and ", " & " };
|
||||
foreach (var sep in andSeps)
|
||||
{
|
||||
if (input.Contains(sep))
|
||||
{
|
||||
var result = new List<string>();
|
||||
foreach (var s in input.Split(sep).Select(x => x.Trim()))
|
||||
{
|
||||
var s2 = SplitAuthor(s);
|
||||
if (s2.Any())
|
||||
{
|
||||
result.AddRange(s2);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (input.Contains(','))
|
||||
{
|
||||
var split = input.Split(',').Select(x => x.Trim()).ToList();
|
||||
if (split[0].Contains(' '))
|
||||
{
|
||||
return split;
|
||||
}
|
||||
}
|
||||
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user