New: Token for track artist (as opposed to album artist) (#1910)

* New: Token for track artist (as opposed to album artist)

* - Move logic to AddTrackTokens instead of separate AddTrackArtistTokens method
- Just use the first artist name

* Update FIleNameSampleService to handle this token properly

* Fall back to album artist if there's no track artist

* Show tokens in naming modal
This commit is contained in:
Daniel Lo Nigro 2021-04-16 04:22:36 -07:00 committed by GitHub
parent f50556d4d5
commit 187672b183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 7 deletions

View File

@ -82,6 +82,12 @@ const trackTitleTokens = [
{ token: '{Track CleanTitle}', example: 'Track Title' }
];
const trackArtistTokens = [
{ token: '{Track ArtistName}', example: 'Artist Name' },
{ token: '{Track ArtistNameThe}', example: 'Artist Name, The' },
{ token: '{Track ArtistCleanName}', example: 'Artist Name' }
];
const qualityTokens = [
{ token: '{Quality Full}', example: 'FLAC Proper' },
{ token: '{Quality Title}', example: 'FLAC' }
@ -411,6 +417,28 @@ class NamingModal extends Component {
</div>
</FieldSet>
<FieldSet legend="Track Artist">
<div className={styles.groups}>
{
trackArtistTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
<FieldSet legend="Quality">
<div className={styles.groups}>
{

View File

@ -4,6 +4,7 @@ using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Music;
using NzbDrone.Core.Organizer;
@ -17,10 +18,13 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
{
private Artist _artist;
private Artist _variousArtists;
private Album _album;
private Album _mixAlbum;
private Medium _medium;
private AlbumRelease _release;
private Track _track1;
private Track _mixTrack1;
private TrackFile _trackFile;
private NamingConfig _namingConfig;
@ -37,6 +41,15 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
})
.Build();
_variousArtists = Builder<Artist>
.CreateNew()
.With(s => s.Name = "Various Artists")
.With(s => s.Metadata = new ArtistMetadata
{
Name = "Various Artists"
})
.Build();
_medium = Builder<Medium>
.CreateNew()
.With(m => m.Number = 3)
@ -55,6 +68,12 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.With(s => s.Disambiguation = "The Best Album")
.Build();
_mixAlbum = Builder<Album>
.CreateNew()
.With(s => s.Title = "Cool Music")
.With(s => s.AlbumType = "Album")
.Build();
_namingConfig = NamingConfig.Default;
_namingConfig.RenameTracks = true;
@ -66,8 +85,17 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.With(e => e.AbsoluteTrackNumber = 6)
.With(e => e.AlbumRelease = _release)
.With(e => e.MediumNumber = _medium.Number)
.With(e => e.ArtistMetadata = _artist.Metadata)
.Build();
_mixTrack1 = Builder<Track>.CreateNew()
.With(e => e.Title = "City Sushi")
.With(e => e.AbsoluteTrackNumber = 1)
.With(e => e.AlbumRelease = _release)
.With(e => e.MediumNumber = _medium.Number)
.With(e => e.ArtistMetadata = _artist.Metadata)
.Build();
_trackFile = Builder<TrackFile>.CreateNew()
.With(e => e.Quality = new QualityModel(Quality.MP3_256))
.With(e => e.ReleaseGroup = "LidarrTest")
@ -461,6 +489,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.With(e => e.Title = "Part 1")
.With(e => e.AbsoluteTrackNumber = 6)
.With(e => e.AlbumRelease = _release)
.With(e => e.ArtistMetadata = new ArtistMetadata { Name = "In The Woods." })
.Build();
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods." }, new Album { Title = "30 Rock" }, _trackFile)
@ -476,6 +505,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.With(e => e.Title = "Part 1")
.With(e => e.AbsoluteTrackNumber = 6)
.With(e => e.AlbumRelease = _release)
.With(e => e.ArtistMetadata = new ArtistMetadata { Name = "In The Woods..." })
.Build();
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods..." }, new Album { Title = "30 Rock" }, _trackFile)
@ -648,5 +678,21 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
.Should().Be(releaseGroup);
}
[Test]
public void should_replace_artist_name_for_Various_Artists_album()
{
_namingConfig.StandardTrackFormat = "{Artist Name}";
Subject.BuildTrackFileName(new List<Track> { _mixTrack1 }, _variousArtists, _mixAlbum, _trackFile)
.Should().Be("Various Artists");
}
[Test]
public void should_replace_track_artist_name_for_Various_Artists_album()
{
_namingConfig.StandardTrackFormat = "{Track ArtistName}";
Subject.BuildTrackFileName(new List<Track> { _mixTrack1 }, _variousArtists, _mixAlbum, _trackFile)
.Should().Be("Linkin Park");
}
}
}

View File

@ -113,7 +113,7 @@ namespace NzbDrone.Core.Organizer
AddArtistTokens(tokenHandlers, artist);
AddAlbumTokens(tokenHandlers, album);
AddMediumTokens(tokenHandlers, tracks.First().AlbumRelease.Value.Media.SingleOrDefault(m => m.Number == tracks.First().MediumNumber));
AddTrackTokens(tokenHandlers, tracks);
AddTrackTokens(tokenHandlers, tracks, artist);
AddTrackFileTokens(tokenHandlers, trackFile);
AddQualityTokens(tokenHandlers, artist, trackFile);
AddMediaInfoTokens(tokenHandlers, trackFile);
@ -301,10 +301,21 @@ namespace NzbDrone.Core.Organizer
tokenHandlers["{Medium Format}"] = m => medium.Format;
}
private void AddTrackTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Track> tracks)
private void AddTrackTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Track> tracks, Artist artist)
{
tokenHandlers["{Track Title}"] = m => GetTrackTitle(tracks, "+");
tokenHandlers["{Track CleanTitle}"] = m => CleanTitle(GetTrackTitle(tracks, "and"));
// Use the track's ArtistMetadata by default, as it will handle the "Various Artists" case
// (where the album artist is "Various Artists" but each track has its own artist). Fall back
// to the album artist if we don't have any track ArtistMetadata for whatever reason.
var firstArtist = tracks.Select(t => t.ArtistMetadata?.Value).FirstOrDefault() ?? artist.Metadata;
if (firstArtist != null)
{
tokenHandlers["{Track ArtistName}"] = m => firstArtist.Name;
tokenHandlers["{Track ArtistCleanName}"] = m => CleanTitle(firstArtist.Name);
tokenHandlers["{Track ArtistNameThe}"] = m => TitleThe(firstArtist.Name);
}
}
private void AddTrackFileTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, TrackFile trackFile)

View File

@ -29,14 +29,15 @@ namespace NzbDrone.Core.Organizer
public FileNameSampleService(IBuildFileNames buildFileNames)
{
_buildFileNames = buildFileNames;
var artistMetadata = new ArtistMetadata
{
Name = "The Artist Name",
Disambiguation = "US Rock Band"
};
_standardArtist = new Artist
{
Metadata = new ArtistMetadata
{
Name = "The Artist Name",
Disambiguation = "US Rock Band"
}
Metadata = artistMetadata
};
_standardAlbum = new Album
@ -86,8 +87,10 @@ namespace NzbDrone.Core.Organizer
_track1 = new Track
{
AlbumRelease = _singleRelease,
Artist = _standardArtist,
AbsoluteTrackNumber = 3,
MediumNumber = 1,
ArtistMetadata = artistMetadata,
Title = "Track Title (1)",
};