-
-
Notifications
You must be signed in to change notification settings - Fork 242
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import album extras for manual imports and downloads
Co-authored-by: TTY Teapot <ttdev@protonmail.com>
- Loading branch information
1 parent
f31ecaf
commit 134c3be
Showing
5 changed files
with
489 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using Moq; | ||
using NUnit.Framework; | ||
using NzbDrone.Common.Disk; | ||
using NzbDrone.Core.Extras; | ||
using NzbDrone.Core.Extras.Others; | ||
using NzbDrone.Core.MediaFiles; | ||
using NzbDrone.Core.MediaFiles.Events; | ||
using NzbDrone.Core.MediaFiles.TrackImport; | ||
using NzbDrone.Core.Music; | ||
using NzbDrone.Core.Organizer; | ||
using NzbDrone.Core.Parser.Model; | ||
using NzbDrone.Core.Profiles.Qualities; | ||
using NzbDrone.Core.Test.Framework; | ||
using NzbDrone.Test.Common; | ||
|
||
namespace NzbDrone.Core.Test.Extras | ||
{ | ||
public class ExtraServiceFixture : CoreTest<ExtraService> | ||
{ | ||
private List<ImportDecision<LocalTrack>> _approvedDecisions; | ||
private string _albumDir; | ||
private Artist _artist; | ||
private Album _album; | ||
private List<string> _albumDirExtraFiles; | ||
private List<string> _downloadDirExtraFiles; | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
var artistDir = @"C:\Test\Music\Foo Fooers".AsOsAgnostic(); | ||
_artist = new Artist() | ||
{ | ||
QualityProfile = new QualityProfile { Items = Qualities.QualityFixture.GetDefaultQualities() }, | ||
Path = artistDir, | ||
}; | ||
_album = new Album() | ||
{ | ||
Id = 15, | ||
Artist = _artist, | ||
Title = "Twenty Thirties" | ||
}; | ||
_albumDir = Path.Join(_artist.Path, $"{_album.Title} (1995) [FLAC]"); | ||
|
||
var release = new AlbumRelease() | ||
{ | ||
AlbumId = _album.Id, | ||
Monitored = true, | ||
}; | ||
_album.AlbumReleases = new List<AlbumRelease> { release }; | ||
|
||
var track = new LocalTrack | ||
{ | ||
Artist = _artist, | ||
Album = _album, | ||
Release = release, | ||
Tracks = new List<Track> { new Track() { Album = _album, } }, | ||
Path = Path.Join(_albumDir, "01 - hurrdurr.flac"), | ||
}; | ||
_approvedDecisions = new () | ||
{ | ||
new ImportDecision<LocalTrack>(track) | ||
}; | ||
|
||
_albumDirExtraFiles = new List<string> | ||
{ | ||
Path.Join(_albumDir, "album.cue"), | ||
Path.Join(_albumDir, "albumfoo_barz.jpg"), | ||
Path.Join(_albumDir, "release.nfo"), | ||
Path.Join(_albumDir, "eac.log"), | ||
}; | ||
|
||
var downloadDir = @"C:\temp\downloads\TT".AsOsAgnostic(); | ||
_downloadDirExtraFiles = new List<string> | ||
{ | ||
Path.Join(downloadDir, "album.cue"), | ||
Path.Join(downloadDir, "cover.jpg"), | ||
Path.Join(downloadDir, "eac.log"), | ||
}; | ||
|
||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetParentFolder( | ||
It.Is<string>(arg => arg.AsOsAgnostic() == _approvedDecisions.First().Item.Path.AsOsAgnostic()))) | ||
.Returns(_albumDir); | ||
|
||
// Rename on by default | ||
var cfg = NamingConfig.Default; | ||
cfg.RenameTracks = true; | ||
Mocker.GetMock<INamingConfigService>().Setup(x => x.GetConfig()).Returns(cfg); | ||
} | ||
|
||
[Test] | ||
public void should_import_extras_during_manual_import_with_naming_config_having_rename_on() | ||
{ | ||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetFiles(It.Is<string>(arg => arg == _albumDir), false)) | ||
.Returns(_approvedDecisions.Select(d => d.Item.Path).Concat(_albumDirExtraFiles)); | ||
|
||
// act | ||
Subject.ImportAlbumExtras(_approvedDecisions, _albumDir); | ||
|
||
// assert | ||
Mocker.GetMock<IOtherExtraFileService>() | ||
.Verify(x => x.Upsert(It.Is<List<OtherExtraFile>>(arg => arg.Count == _albumDirExtraFiles.Count))); | ||
} | ||
|
||
[Test] | ||
public void should_import_extras_from_download_location() | ||
{ | ||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetFiles(It.Is<string>(arg => arg == _albumDir), false)) | ||
.Returns(_approvedDecisions.Select(d => d.Item.Path).Concat(_downloadDirExtraFiles)); | ||
|
||
Subject.ImportAlbumExtras(_approvedDecisions, _albumDir); | ||
|
||
Mocker.GetMock<IOtherExtraFileService>() | ||
.Verify(x => x.Upsert(It.Is<List<OtherExtraFile>>(arg => arg.Count == _downloadDirExtraFiles.Count))); | ||
foreach (var sourcePath in _downloadDirExtraFiles) | ||
{ | ||
Mocker.GetMock<IDiskTransferService>() | ||
.Verify(x => x.TransferFile( | ||
It.Is<string>(arg => arg.AsOsAgnostic() == sourcePath.AsOsAgnostic()), | ||
It.Is<string>(arg => arg.AsOsAgnostic().StartsWith(_albumDir.AsOsAgnostic())), | ||
It.IsAny<TransferMode>(), | ||
It.IsAny<bool>())); | ||
} | ||
} | ||
|
||
[Test] | ||
public void should_not_import_extras_with_naming_cfg_having_rename_off() | ||
{ | ||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetFiles(It.Is<string>(arg => arg == _albumDir), false)) | ||
.Returns(_approvedDecisions.Select(d => d.Item.Path).Concat(_albumDirExtraFiles)); | ||
|
||
var cfg = NamingConfig.Default; | ||
cfg.RenameTracks = false; // explicitly set for readability | ||
SetupNamingConfig(cfg); | ||
|
||
Subject.ImportAlbumExtras(_approvedDecisions, _albumDir); | ||
|
||
Mocker.GetMock<IOtherExtraFileService>().VerifyNoOtherCalls(); | ||
} | ||
|
||
[TestCase(false)] | ||
[TestCase(true)] | ||
public void should_not_import_extras_when_no_separate_album_dir_set(bool testStandardTrackFormat) | ||
{ | ||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetFiles(It.Is<string>(arg => arg == _albumDir), false)) | ||
.Returns(_approvedDecisions.Select(d => d.Item.Path).Concat(_albumDirExtraFiles)); | ||
|
||
var cfg = NamingConfig.Default; | ||
cfg.RenameTracks = true; | ||
|
||
// modify either standard or multidisc format to test both branches: | ||
if (testStandardTrackFormat) | ||
{ | ||
cfg.StandardTrackFormat = "{Artist Name} - {Album Title} - {track:00} - {Track Title}"; | ||
} | ||
else | ||
{ | ||
cfg.MultiDiscTrackFormat = "{Medium Format} {medium:00}/{Artist Name} - {Album Title} - {track:00} - {Track Title}"; | ||
} | ||
|
||
SetupNamingConfig(cfg); | ||
|
||
Subject.ImportAlbumExtras(_approvedDecisions, _albumDir); | ||
|
||
Mocker.GetMock<IOtherExtraFileService>().VerifyNoOtherCalls(); | ||
} | ||
|
||
[TestCase("{Album Title} ({Release Year})")] | ||
[TestCase("{ALBUM TITLE} ({Release Year})")] | ||
[TestCase("{Album Title}")] | ||
[TestCase("{Album.Title}")] | ||
[TestCase("{Album_Title}")] | ||
public void should_import_extras_rename_pattern_contains_album_title(string albumDirPattern) | ||
{ | ||
Mocker.GetMock<IDiskProvider>() | ||
.Setup(x => x.GetFiles(It.Is<string>(arg => arg == _albumDir), false)) | ||
.Returns(_approvedDecisions.Select(d => d.Item.Path).Concat(_albumDirExtraFiles)); | ||
|
||
var cfg = NamingConfig.Default; | ||
cfg.RenameTracks = true; | ||
|
||
cfg.StandardTrackFormat = cfg.StandardTrackFormat | ||
.Replace("{Album Title} ({Release Year})", albumDirPattern); | ||
cfg.MultiDiscTrackFormat = cfg.MultiDiscTrackFormat | ||
.Replace("{Album Title} ({Release Year})", albumDirPattern); | ||
|
||
SetupNamingConfig(cfg); | ||
|
||
// act | ||
Subject.ImportAlbumExtras(_approvedDecisions, _albumDir); | ||
|
||
// assert | ||
Mocker.GetMock<IOtherExtraFileService>() | ||
.Verify(x => x.Upsert(It.Is<List<OtherExtraFile>>(arg => arg.Count == _albumDirExtraFiles.Count))); | ||
} | ||
|
||
[Test] | ||
public void should_move_album_extra_on_artist_renamed_event() | ||
{ | ||
var newDir = Path.Combine(_albumDir, "new_subdir").AsOsAgnostic(); | ||
var renamed = new List<RenamedTrackFile>(); | ||
foreach (var import in _approvedDecisions) | ||
{ | ||
renamed.Add(new RenamedTrackFile() | ||
{ | ||
PreviousPath = import.Item.Path, | ||
TrackFile = new TrackFile() | ||
{ | ||
Id = 11, | ||
Album = _album, | ||
AlbumId = _album.Id, | ||
Path = import.Item.Path.Replace(_albumDir, newDir), | ||
Tracks = new List<Track>() | ||
{ | ||
new Track() { Album = _album, Artist = _artist, TrackFileId = 11 }, | ||
} | ||
}, | ||
}); | ||
} | ||
|
||
var relativePathBeforeMove = Path.Combine(new DirectoryInfo(_albumDir).Name, "album.cue"); | ||
var albumExtra = new OtherExtraFile | ||
{ | ||
Id = 251, | ||
AlbumId = _album.Id, | ||
ArtistId = _album.ArtistId, | ||
RelativePath = relativePathBeforeMove, | ||
Extension = ".cue", | ||
Added = DateTime.UtcNow, | ||
TrackFileId = null, | ||
}; | ||
|
||
Mocker.GetMock<IMediaFileService>().Setup(x => x.GetFilesByArtist(_album.ArtistId)) | ||
.Returns(renamed.Select(x => x.TrackFile).ToList()); | ||
Mocker.GetMock<ITrackService>().Setup(x => x.GetTracksByArtist(_album.ArtistId)) | ||
.Returns(renamed.SelectMany(x => x.TrackFile.Tracks.Value).ToList()); | ||
Mocker.GetMock<IOtherExtraFileService>().Setup(x => x.GetFilesByArtist(_album.ArtistId)) | ||
.Returns(new List<OtherExtraFile>() { albumExtra }); | ||
|
||
// act | ||
Subject.Handle(new ArtistRenamedEvent(_artist, renamed)); | ||
|
||
// assert | ||
Mocker.GetMock<IDiskProvider>() | ||
.Verify(x => x.MoveFile( | ||
It.Is<string>(arg => arg.Contains(relativePathBeforeMove)), | ||
It.Is<string>(arg => arg.Contains(newDir)), | ||
It.IsAny<bool>()), Times.Once); | ||
Mocker.GetMock<IOtherExtraFileService>() | ||
.Verify(x => x.Upsert(It.Is<List<OtherExtraFile>>(arg => arg.Count == 1))); | ||
} | ||
|
||
/// <summary> | ||
/// Set <paramref name="cfg"/> as the current naming configuration for the current test. | ||
/// </summary> | ||
/// <param name="cfg">The naming config to return from <see cref="INamingConfigService"/>.</param> | ||
private void SetupNamingConfig(NamingConfig cfg) | ||
{ | ||
Mocker.GetMock<INamingConfigService>().Setup(x => x.GetConfig()).Returns(cfg); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/NzbDrone.Core/Datastore/Migration/076_relax_not_null_constraints_extra_files.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using FluentMigrator; | ||
using NzbDrone.Core.Datastore.Migration.Framework; | ||
|
||
namespace NzbDrone.Core.Datastore.Migration | ||
{ | ||
[Migration(076)] | ||
public class relax_not_null_constraints_extra_files : NzbDroneMigrationBase | ||
{ | ||
protected override void MainDbUpgrade() | ||
{ | ||
Rename.Column("TrackFileId").OnTable("ExtraFiles").To("TrackFileIdLegacy"); | ||
Alter.Table("ExtraFiles").AddColumn("TrackFileId").AsInt64().Nullable(); | ||
Execute.Sql("UPDATE \"ExtraFiles\" SET \"TrackFileId\" = \"TrackFileIdLegacy\""); | ||
Delete.Column("TrackFileIdLegacy").FromTable("ExtraFiles"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.