mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
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:
parent
f50556d4d5
commit
187672b183
4 changed files with 95 additions and 7 deletions
|
@ -82,6 +82,12 @@ const trackTitleTokens = [
|
||||||
{ token: '{Track CleanTitle}', example: 'Track Title' }
|
{ 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 = [
|
const qualityTokens = [
|
||||||
{ token: '{Quality Full}', example: 'FLAC Proper' },
|
{ token: '{Quality Full}', example: 'FLAC Proper' },
|
||||||
{ token: '{Quality Title}', example: 'FLAC' }
|
{ token: '{Quality Title}', example: 'FLAC' }
|
||||||
|
@ -411,6 +417,28 @@ class NamingModal extends Component {
|
||||||
</div>
|
</div>
|
||||||
</FieldSet>
|
</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">
|
<FieldSet legend="Quality">
|
||||||
<div className={styles.groups}>
|
<div className={styles.groups}>
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Music;
|
using NzbDrone.Core.Music;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
|
@ -17,10 +18,13 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
|
public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
|
||||||
{
|
{
|
||||||
private Artist _artist;
|
private Artist _artist;
|
||||||
|
private Artist _variousArtists;
|
||||||
private Album _album;
|
private Album _album;
|
||||||
|
private Album _mixAlbum;
|
||||||
private Medium _medium;
|
private Medium _medium;
|
||||||
private AlbumRelease _release;
|
private AlbumRelease _release;
|
||||||
private Track _track1;
|
private Track _track1;
|
||||||
|
private Track _mixTrack1;
|
||||||
private TrackFile _trackFile;
|
private TrackFile _trackFile;
|
||||||
private NamingConfig _namingConfig;
|
private NamingConfig _namingConfig;
|
||||||
|
|
||||||
|
@ -37,6 +41,15 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
_variousArtists = Builder<Artist>
|
||||||
|
.CreateNew()
|
||||||
|
.With(s => s.Name = "Various Artists")
|
||||||
|
.With(s => s.Metadata = new ArtistMetadata
|
||||||
|
{
|
||||||
|
Name = "Various Artists"
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
_medium = Builder<Medium>
|
_medium = Builder<Medium>
|
||||||
.CreateNew()
|
.CreateNew()
|
||||||
.With(m => m.Number = 3)
|
.With(m => m.Number = 3)
|
||||||
|
@ -55,6 +68,12 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
.With(s => s.Disambiguation = "The Best Album")
|
.With(s => s.Disambiguation = "The Best Album")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
_mixAlbum = Builder<Album>
|
||||||
|
.CreateNew()
|
||||||
|
.With(s => s.Title = "Cool Music")
|
||||||
|
.With(s => s.AlbumType = "Album")
|
||||||
|
.Build();
|
||||||
|
|
||||||
_namingConfig = NamingConfig.Default;
|
_namingConfig = NamingConfig.Default;
|
||||||
_namingConfig.RenameTracks = true;
|
_namingConfig.RenameTracks = true;
|
||||||
|
|
||||||
|
@ -66,8 +85,17 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
.With(e => e.AbsoluteTrackNumber = 6)
|
.With(e => e.AbsoluteTrackNumber = 6)
|
||||||
.With(e => e.AlbumRelease = _release)
|
.With(e => e.AlbumRelease = _release)
|
||||||
.With(e => e.MediumNumber = _medium.Number)
|
.With(e => e.MediumNumber = _medium.Number)
|
||||||
|
.With(e => e.ArtistMetadata = _artist.Metadata)
|
||||||
.Build();
|
.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()
|
_trackFile = Builder<TrackFile>.CreateNew()
|
||||||
.With(e => e.Quality = new QualityModel(Quality.MP3_256))
|
.With(e => e.Quality = new QualityModel(Quality.MP3_256))
|
||||||
.With(e => e.ReleaseGroup = "LidarrTest")
|
.With(e => e.ReleaseGroup = "LidarrTest")
|
||||||
|
@ -461,6 +489,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
.With(e => e.Title = "Part 1")
|
.With(e => e.Title = "Part 1")
|
||||||
.With(e => e.AbsoluteTrackNumber = 6)
|
.With(e => e.AbsoluteTrackNumber = 6)
|
||||||
.With(e => e.AlbumRelease = _release)
|
.With(e => e.AlbumRelease = _release)
|
||||||
|
.With(e => e.ArtistMetadata = new ArtistMetadata { Name = "In The Woods." })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods." }, new Album { Title = "30 Rock" }, _trackFile)
|
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.Title = "Part 1")
|
||||||
.With(e => e.AbsoluteTrackNumber = 6)
|
.With(e => e.AbsoluteTrackNumber = 6)
|
||||||
.With(e => e.AlbumRelease = _release)
|
.With(e => e.AlbumRelease = _release)
|
||||||
|
.With(e => e.ArtistMetadata = new ArtistMetadata { Name = "In The Woods..." })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
Subject.BuildTrackFileName(new List<Track> { track }, new Artist { Name = "In The Woods..." }, new Album { Title = "30 Rock" }, _trackFile)
|
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)
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
.Should().Be(releaseGroup);
|
.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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
AddArtistTokens(tokenHandlers, artist);
|
AddArtistTokens(tokenHandlers, artist);
|
||||||
AddAlbumTokens(tokenHandlers, album);
|
AddAlbumTokens(tokenHandlers, album);
|
||||||
AddMediumTokens(tokenHandlers, tracks.First().AlbumRelease.Value.Media.SingleOrDefault(m => m.Number == tracks.First().MediumNumber));
|
AddMediumTokens(tokenHandlers, tracks.First().AlbumRelease.Value.Media.SingleOrDefault(m => m.Number == tracks.First().MediumNumber));
|
||||||
AddTrackTokens(tokenHandlers, tracks);
|
AddTrackTokens(tokenHandlers, tracks, artist);
|
||||||
AddTrackFileTokens(tokenHandlers, trackFile);
|
AddTrackFileTokens(tokenHandlers, trackFile);
|
||||||
AddQualityTokens(tokenHandlers, artist, trackFile);
|
AddQualityTokens(tokenHandlers, artist, trackFile);
|
||||||
AddMediaInfoTokens(tokenHandlers, trackFile);
|
AddMediaInfoTokens(tokenHandlers, trackFile);
|
||||||
|
@ -301,10 +301,21 @@ namespace NzbDrone.Core.Organizer
|
||||||
tokenHandlers["{Medium Format}"] = m => medium.Format;
|
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 Title}"] = m => GetTrackTitle(tracks, "+");
|
||||||
tokenHandlers["{Track CleanTitle}"] = m => CleanTitle(GetTrackTitle(tracks, "and"));
|
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)
|
private void AddTrackFileTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, TrackFile trackFile)
|
||||||
|
|
|
@ -29,14 +29,15 @@ namespace NzbDrone.Core.Organizer
|
||||||
public FileNameSampleService(IBuildFileNames buildFileNames)
|
public FileNameSampleService(IBuildFileNames buildFileNames)
|
||||||
{
|
{
|
||||||
_buildFileNames = buildFileNames;
|
_buildFileNames = buildFileNames;
|
||||||
|
var artistMetadata = new ArtistMetadata
|
||||||
|
{
|
||||||
|
Name = "The Artist Name",
|
||||||
|
Disambiguation = "US Rock Band"
|
||||||
|
};
|
||||||
|
|
||||||
_standardArtist = new Artist
|
_standardArtist = new Artist
|
||||||
{
|
{
|
||||||
Metadata = new ArtistMetadata
|
Metadata = artistMetadata
|
||||||
{
|
|
||||||
Name = "The Artist Name",
|
|
||||||
Disambiguation = "US Rock Band"
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_standardAlbum = new Album
|
_standardAlbum = new Album
|
||||||
|
@ -86,8 +87,10 @@ namespace NzbDrone.Core.Organizer
|
||||||
_track1 = new Track
|
_track1 = new Track
|
||||||
{
|
{
|
||||||
AlbumRelease = _singleRelease,
|
AlbumRelease = _singleRelease,
|
||||||
|
Artist = _standardArtist,
|
||||||
AbsoluteTrackNumber = 3,
|
AbsoluteTrackNumber = 3,
|
||||||
MediumNumber = 1,
|
MediumNumber = 1,
|
||||||
|
ArtistMetadata = artistMetadata,
|
||||||
|
|
||||||
Title = "Track Title (1)",
|
Title = "Track Title (1)",
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue