New: Cache spotify -> musicbrainz mapping

pull/1689/head
ta264 5 years ago committed by Qstick
parent 8280c85b94
commit 4655cbe0c2

@ -120,9 +120,19 @@ namespace NzbDrone.Core.Test.ImportListTests
}
[Test]
public void should_not_search_if_album_title_and_album_id()
public void should_search_with_lidarr_id_if_album_id_and_no_artist_id()
{
WithAlbum();
WithAlbumId();
Subject.Execute(new ImportListSyncCommand());
Mocker.GetMock<ISearchForNewAlbum>()
.Verify(v => v.SearchForNewAlbum($"lidarr:{_importListReports.First().AlbumMusicBrainzId}", null), Times.Once());
}
[Test]
public void should_not_search_if_album_id_and_artist_id()
{
WithArtistId();
WithAlbumId();
Subject.Execute(new ImportListSyncCommand());

@ -0,0 +1,346 @@
using System;
using System.Collections.Generic;
using System.Net;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.ImportLists.Spotify;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ImportListTests
{
[TestFixture]
// the base import list class is abstract so use the followed artists one
public class SpotifyMappingFixture : CoreTest<SpotifyFollowedArtists>
{
[SetUp]
public void Setup()
{
Mocker.SetConstant<ILidarrCloudRequestBuilder>(new LidarrCloudRequestBuilder());
Mocker.SetConstant<IMetadataRequestBuilder>(Mocker.Resolve<MetadataRequestBuilder>());
}
[Test]
public void map_artist_should_return_name_if_id_null()
{
var data = new SpotifyImportListItemInfo
{
Artist = "Adele"
};
Subject.MapArtistItem(data);
data.Artist.Should().Be("Adele");
data.ArtistMusicBrainzId.Should().BeNull();
data.Album.Should().BeNull();
data.AlbumMusicBrainzId.Should().BeNull();
}
[Test]
public void map_artist_should_set_id_0_if_no_match()
{
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Get<ArtistResource>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>((x) => new HttpResponse<ArtistResource>(new HttpResponse(x, new HttpHeader(), new byte[0], HttpStatusCode.NotFound)));
var data = new SpotifyImportListItemInfo
{
Artist = "Adele",
ArtistSpotifyId = "id"
};
Subject.MapArtistItem(data);
data.ArtistMusicBrainzId.Should().Be("0");
}
[Test]
public void map_artist_should_not_update_id_if_http_throws()
{
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Get<ArtistResource>(It.IsAny<HttpRequest>()))
.Throws(new Exception("Dummy exception"));
var data = new SpotifyImportListItemInfo
{
Artist = "Adele",
ArtistSpotifyId = "id"
};
Subject.MapArtistItem(data);
data.ArtistMusicBrainzId.Should().BeNull();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void map_artist_should_work()
{
UseRealHttp();
var data = new SpotifyImportListItemInfo
{
Artist = "Adele",
ArtistSpotifyId = "4dpARuHxo51G3z768sgnrY"
};
Subject.MapArtistItem(data);
data.Should().NotBeNull();
data.Artist.Should().Be("Adele");
data.ArtistMusicBrainzId.Should().Be("cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493");
data.Album.Should().BeNull();
data.AlbumMusicBrainzId.Should().BeNull();
}
[Test]
public void map_album_should_return_name_if_uri_null()
{
var data = new SpotifyImportListItemInfo
{
Album = "25",
Artist = "Adele"
};
Subject.MapAlbumItem(data);
data.Should().NotBeNull();
data.Artist.Should().Be("Adele");
data.ArtistMusicBrainzId.Should().BeNull();
data.Album.Should().Be("25");
data.AlbumMusicBrainzId.Should().BeNull();
}
[Test]
public void map_album_should_set_id_0_if_no_match()
{
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Get<AlbumResource>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>((x) => new HttpResponse<AlbumResource>(new HttpResponse(x, new HttpHeader(), new byte[0], HttpStatusCode.NotFound)));
var data = new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "id",
Artist = "Adele"
};
Subject.MapAlbumItem(data);
data.AlbumMusicBrainzId.Should().Be("0");
}
[Test]
public void map_album_should_not_update_id_if_http_throws()
{
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Get<AlbumResource>(It.IsAny<HttpRequest>()))
.Throws(new Exception("Dummy exception"));
var data = new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "id",
Artist = "Adele"
};
Subject.MapAlbumItem(data);
data.Should().NotBeNull();
data.Artist.Should().Be("Adele");
data.ArtistMusicBrainzId.Should().BeNull();
data.Album.Should().Be("25");
data.AlbumMusicBrainzId.Should().BeNull();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void map_album_should_work()
{
UseRealHttp();
var data = new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele"
};
Subject.MapAlbumItem(data);
data.Should().NotBeNull();
data.Artist.Should().Be("Adele");
data.Album.Should().Be("25");
data.AlbumMusicBrainzId.Should().Be("5537624c-3d2f-4f5c-8099-df916082c85c");
}
[Test]
public void map_spotify_releases_should_only_map_album_id_for_album()
{
var data = new List<SpotifyImportListItemInfo>
{
new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele",
ArtistSpotifyId = "4dpARuHxo51G3z768sgnrY"
}
};
var map = new List<SpotifyMap>
{
new SpotifyMap
{
SpotifyId = "7uwTHXmFa1Ebi5flqBosig",
MusicbrainzId = "5537624c-3d2f-4f5c-8099-df916082c85c"
},
new SpotifyMap
{
SpotifyId = "4dpARuHxo51G3z768sgnrY",
MusicbrainzId = "cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493"
}
};
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Post<List<SpotifyMap>>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse<List<SpotifyMap>>(new HttpResponse(r, new HttpHeader(), map.ToJson())));
var result = Subject.MapSpotifyReleases(data);
result[0].AlbumMusicBrainzId.Should().Be("5537624c-3d2f-4f5c-8099-df916082c85c");
result[0].ArtistMusicBrainzId.Should().BeNull();
}
[Test]
public void map_spotify_releases_should_map_artist_id_for_artist()
{
var data = new List<SpotifyImportListItemInfo>
{
new SpotifyImportListItemInfo
{
Artist = "Adele",
ArtistSpotifyId = "4dpARuHxo51G3z768sgnrY"
}
};
var map = new List<SpotifyMap>
{
new SpotifyMap
{
SpotifyId = "7uwTHXmFa1Ebi5flqBosig",
MusicbrainzId = "5537624c-3d2f-4f5c-8099-df916082c85c"
},
new SpotifyMap
{
SpotifyId = "4dpARuHxo51G3z768sgnrY",
MusicbrainzId = "cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493"
}
};
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Post<List<SpotifyMap>>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse<List<SpotifyMap>>(new HttpResponse(r, new HttpHeader(), map.ToJson())));
var result = Subject.MapSpotifyReleases(data);
result[0].ArtistMusicBrainzId.Should().Be("cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493");
}
[Test]
public void map_spotify_releases_should_drop_not_found()
{
var data = new List<SpotifyImportListItemInfo>
{
new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele"
}
};
var map = new List<SpotifyMap>
{
new SpotifyMap
{
SpotifyId = "7uwTHXmFa1Ebi5flqBosig",
MusicbrainzId = "0"
}
};
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Post<List<SpotifyMap>>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse<List<SpotifyMap>>(new HttpResponse(r, new HttpHeader(), map.ToJson())));
var result = Subject.MapSpotifyReleases(data);
result.Should().BeEmpty();
}
[Test]
public void map_spotify_releases_should_catch_exception_from_api()
{
var data = new List<SpotifyImportListItemInfo>
{
new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele"
}
};
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Post<List<SpotifyMap>>(It.IsAny<HttpRequest>()))
.Throws(new Exception("Dummy exception"));
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Get<AlbumResource>(It.IsAny<HttpRequest>()))
.Throws(new Exception("Dummy exception"));
var result = Subject.MapSpotifyReleases(data);
result.Should().NotBeNull();
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void map_spotify_releases_should_cope_with_duplicate_spotify_ids()
{
var data = new List<SpotifyImportListItemInfo>
{
new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele"
},
new SpotifyImportListItemInfo
{
Album = "25",
AlbumSpotifyId = "7uwTHXmFa1Ebi5flqBosig",
Artist = "Adele"
}
};
var map = new List<SpotifyMap>
{
new SpotifyMap
{
SpotifyId = "7uwTHXmFa1Ebi5flqBosig",
MusicbrainzId = "5537624c-3d2f-4f5c-8099-df916082c85c"
}
};
Mocker.GetMock<IHttpClient>()
.Setup(x => x.Post<List<SpotifyMap>>(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse<List<SpotifyMap>>(new HttpResponse(r, new HttpHeader(), map.ToJson())));
var result = Subject.MapSpotifyReleases(data);
result.Should().HaveCount(2);
result[0].AlbumMusicBrainzId.Should().Be("5537624c-3d2f-4f5c-8099-df916082c85c");
result[1].AlbumMusicBrainzId.Should().Be("5537624c-3d2f-4f5c-8099-df916082c85c");
}
}
}

@ -104,6 +104,18 @@ namespace NzbDrone.Core.ImportLists
}
// Map artist ID if we only have album ID
if (report.AlbumMusicBrainzId.IsNotNullOrWhiteSpace() && report.ArtistMusicBrainzId.IsNullOrWhiteSpace())
{
var mappedAlbum = _albumSearchService.SearchForNewAlbum($"lidarr:{report.AlbumMusicBrainzId}", null)
.FirstOrDefault();
if (mappedAlbum == null) continue;
report.Artist = mappedAlbum.ArtistMetadata?.Value?.Name;
report.ArtistMusicBrainzId = mappedAlbum?.ArtistMetadata?.Value?.ForeignArtistId;
}
// Map MBid if we only have a artist name
if (report.ArtistMusicBrainzId.IsNullOrWhiteSpace() && report.Artist.IsNotNullOrWhiteSpace())
{

@ -3,6 +3,7 @@ using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using SpotifyAPI.Web;
@ -18,21 +19,22 @@ namespace NzbDrone.Core.ImportLists.Spotify
public class SpotifyFollowedArtists : SpotifyImportListBase<SpotifyFollowedArtistsSettings>
{
public SpotifyFollowedArtists(ISpotifyProxy spotifyProxy,
IMetadataRequestBuilder requestBuilder,
IImportListStatusService importListStatusService,
IImportListRepository importListRepository,
IConfigService configService,
IParsingService parsingService,
IHttpClient httpClient,
Logger logger)
: base(spotifyProxy, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
: base(spotifyProxy, requestBuilder, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
{
}
public override string Name => "Spotify Followed Artists";
public override IList<ImportListItemInfo> Fetch(SpotifyWebAPI api)
public override IList<SpotifyImportListItemInfo> Fetch(SpotifyWebAPI api)
{
var result = new List<ImportListItemInfo>();
var result = new List<SpotifyImportListItemInfo>();
var followedArtists = _spotifyProxy.GetFollowedArtists(this, api);
var artists = followedArtists?.Artists;
@ -61,12 +63,14 @@ namespace NzbDrone.Core.ImportLists.Spotify
return result;
}
private ImportListItemInfo ParseFullArtist(FullArtist artist)
private SpotifyImportListItemInfo ParseFullArtist(FullArtist artist)
{
if (artist?.Name.IsNotNullOrWhiteSpace() ?? false)
{
return new ImportListItemInfo {
return new SpotifyImportListItemInfo
{
Artist = artist.Name,
ArtistSpotifyId = artist.Id
};
}

@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
@ -21,8 +26,10 @@ namespace NzbDrone.Core.ImportLists.Spotify
private IImportListRepository _importListRepository;
protected ISpotifyProxy _spotifyProxy;
private readonly IMetadataRequestBuilder _requestBuilder;
protected SpotifyImportListBase(ISpotifyProxy spotifyProxy,
IMetadataRequestBuilder requestBuilder,
IImportListStatusService importListStatusService,
IImportListRepository importListRepository,
IConfigService configService,
@ -34,6 +41,7 @@ namespace NzbDrone.Core.ImportLists.Spotify
_httpClient = httpClient;
_importListRepository = importListRepository;
_spotifyProxy = spotifyProxy;
_requestBuilder = requestBuilder;
}
public override ImportListType ListType => ImportListType.Spotify;
@ -93,15 +101,20 @@ namespace NzbDrone.Core.ImportLists.Spotify
public override IList<ImportListItemInfo> Fetch()
{
IList<SpotifyImportListItemInfo> releases;
using (var api = GetApi())
{
_logger.Debug("Starting spotify import list sync");
var releases = Fetch(api);
return CleanupListItems(releases);
releases = Fetch(api);
}
// map to musicbrainz ids
releases = MapSpotifyReleases(releases);
return CleanupListItems(releases);
}
public abstract IList<ImportListItemInfo> Fetch(SpotifyWebAPI api);
public abstract IList<SpotifyImportListItemInfo> Fetch(SpotifyWebAPI api);
protected DateTime ParseSpotifyDate(string date, string precision)
{
@ -128,6 +141,156 @@ namespace NzbDrone.Core.ImportLists.Spotify
return DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result) ? result : default(DateTime);
}
public IList<SpotifyImportListItemInfo> MapSpotifyReleases(IList<SpotifyImportListItemInfo> items)
{
// first pass bulk lookup, server won't do search
var spotifyIds = items.Select(x => x.ArtistSpotifyId)
.Concat(items.Select(x => x.AlbumSpotifyId))
.Where(x => x.IsNotNullOrWhiteSpace())
.Distinct();
var httpRequest = _requestBuilder.GetRequestBuilder().Create()
.SetSegment("route", "spotify/lookup")
.Build();
httpRequest.SetContent(spotifyIds.ToJson());
httpRequest.Headers.ContentType = "application/json";
_logger.Trace($"Requesting maps for:\n{spotifyIds.ToJson()}");
Dictionary<string, string> map;
try
{
var httpResponse = _httpClient.Post<List<SpotifyMap>>(httpRequest);
var mapList = httpResponse.Resource;
// Generate a mapping dictionary.
// The API will return 0 to mean it has previously searched and can't find the item.
// null means that it has never been searched before.
map = mapList.Where(x => x.MusicbrainzId.IsNotNullOrWhiteSpace())
.ToDictionary(x => x.SpotifyId, x => x.MusicbrainzId);
}
catch (Exception e)
{
_logger.Error(e);
map = new Dictionary<string, string>();
}
_logger.Trace("Got mapping:\n{0}", map.ToJson());
foreach (var item in items)
{
if (item.AlbumSpotifyId.IsNotNullOrWhiteSpace())
{
if (map.ContainsKey(item.AlbumSpotifyId))
{
item.AlbumMusicBrainzId = map[item.AlbumSpotifyId];
}
else
{
MapAlbumItem(item);
}
}
else if (item.ArtistSpotifyId.IsNotNullOrWhiteSpace())
{
if (map.ContainsKey(item.ArtistSpotifyId))
{
item.ArtistMusicBrainzId = map[item.ArtistSpotifyId];
}
else
{
MapArtistItem(item);
}
}
}
// Strip out items where mapped to not found
return items.Where(x => x.AlbumMusicBrainzId != "0" && x.ArtistMusicBrainzId != "0").ToList();
}
public void MapArtistItem(SpotifyImportListItemInfo item)
{
if (item.ArtistSpotifyId.IsNullOrWhiteSpace())
{
return;
}
var httpRequest = _requestBuilder.GetRequestBuilder().Create()
.SetSegment("route", $"spotify/artist/{item.ArtistSpotifyId}")
.Build();
httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true;
try
{
var response = _httpClient.Get<ArtistResource>(httpRequest);
if (response.HasHttpError)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
item.ArtistMusicBrainzId = "0";
return;
}
else
{
throw new HttpException(httpRequest, response);
}
}
item.ArtistMusicBrainzId = response.Resource.Id;
}
catch (HttpException e)
{
_logger.Warn(e, "Unable to communicate with LidarrAPI");
}
catch (Exception e)
{
_logger.Error(e);
}
}
public void MapAlbumItem(SpotifyImportListItemInfo item)
{
if (item.AlbumSpotifyId.IsNullOrWhiteSpace())
{
return;
}
var httpRequest = _requestBuilder.GetRequestBuilder().Create()
.SetSegment("route", $"spotify/album/{item.AlbumSpotifyId}")
.Build();
httpRequest.AllowAutoRedirect = true;
httpRequest.SuppressHttpError = true;
try
{
var response = _httpClient.Get<AlbumResource>(httpRequest);
if (response.HasHttpError)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
item.AlbumMusicBrainzId = "0";
return;
}
else
{
throw new HttpException(httpRequest, response);
}
}
item.ArtistMusicBrainzId = response.Resource.ArtistId;
item.AlbumMusicBrainzId = response.Resource.Id;
}
catch (HttpException e)
{
_logger.Warn(e, "Unable to communicate with LidarrAPI");
}
catch (Exception e)
{
_logger.Error(e);
}
}
protected override void Test(List<ValidationFailure> failures)
{
failures.AddIfNotNull(TestConnection());

@ -0,0 +1,15 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.ImportLists.Spotify
{
public class SpotifyImportListItemInfo : ImportListItemInfo
{
public string ArtistSpotifyId { get; set; }
public string AlbumSpotifyId { get; set; }
public override string ToString()
{
return string.Format("[{0}] {1}", ArtistSpotifyId, AlbumSpotifyId);
}
}
}

@ -0,0 +1,8 @@
namespace NzbDrone.Core.ImportLists.Spotify
{
public class SpotifyMap
{
public string SpotifyId { get; set; }
public string MusicbrainzId { get; set; }
}
}

@ -5,8 +5,8 @@ using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
using SpotifyAPI.Web;
using SpotifyAPI.Web.Models;
@ -16,30 +16,31 @@ namespace NzbDrone.Core.ImportLists.Spotify
public class SpotifyPlaylist : SpotifyImportListBase<SpotifyPlaylistSettings>
{
public SpotifyPlaylist(ISpotifyProxy spotifyProxy,
IMetadataRequestBuilder requestBuilder,
IImportListStatusService importListStatusService,
IImportListRepository importListRepository,
IConfigService configService,
IParsingService parsingService,
IHttpClient httpClient,
Logger logger)
: base(spotifyProxy, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
: base(spotifyProxy, requestBuilder, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
{
}
public override string Name => "Spotify Playlists";
public override IList<ImportListItemInfo> Fetch(SpotifyWebAPI api)
public override IList<SpotifyImportListItemInfo> Fetch(SpotifyWebAPI api)
{
return Settings.PlaylistIds.SelectMany(x => Fetch(api, x)).ToList();
}
public IList<ImportListItemInfo> Fetch(SpotifyWebAPI api, string playlistId)
public IList<SpotifyImportListItemInfo> Fetch(SpotifyWebAPI api, string playlistId)
{
var result = new List<ImportListItemInfo>();
var result = new List<SpotifyImportListItemInfo>();
_logger.Trace($"Processing playlist {playlistId}");
var playlistTracks = _spotifyProxy.GetPlaylistTracks(this, api, playlistId, "next, items(track(name, album(name,artists)))");
var playlistTracks = _spotifyProxy.GetPlaylistTracks(this, api, playlistId, "next, items(track(name, artists(id, name), album(id, name, release_date, release_date_precision, artists(id, name))))");
while (true)
{
@ -64,20 +65,23 @@ namespace NzbDrone.Core.ImportLists.Spotify
return result;
}
private ImportListItemInfo ParsePlaylistTrack(PlaylistTrack playlistTrack)
private SpotifyImportListItemInfo ParsePlaylistTrack(PlaylistTrack playlistTrack)
{
// From spotify docs: "Note, a track object may be null. This can happen if a track is no longer available."
if (playlistTrack?.Track?.Album != null)
{
var album = playlistTrack.Track.Album;
var albumName = album.Name;
var artistName = album.Artists?.FirstOrDefault()?.Name ?? playlistTrack.Track?.Artists?.FirstOrDefault()?.Name;
if (albumName.IsNotNullOrWhiteSpace() && artistName.IsNotNullOrWhiteSpace())
{
return new ImportListItemInfo {
return new SpotifyImportListItemInfo
{
Artist = artistName,
Album = albumName,
Album = album.Name,
AlbumSpotifyId = album.Id,
ReleaseDate = ParseSpotifyDate(album.ReleaseDate, album.ReleaseDatePrecision)
};
}

@ -4,6 +4,7 @@ using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using SpotifyAPI.Web;
@ -19,21 +20,22 @@ namespace NzbDrone.Core.ImportLists.Spotify
public class SpotifySavedAlbums : SpotifyImportListBase<SpotifySavedAlbumsSettings>
{
public SpotifySavedAlbums(ISpotifyProxy spotifyProxy,
IMetadataRequestBuilder requestBuilder,
IImportListStatusService importListStatusService,
IImportListRepository importListRepository,
IConfigService configService,
IParsingService parsingService,
IHttpClient httpClient,
Logger logger)
: base(spotifyProxy, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
: base(spotifyProxy, requestBuilder, importListStatusService, importListRepository, configService, parsingService, httpClient, logger)
{
}
public override string Name => "Spotify Saved Albums";
public override IList<ImportListItemInfo> Fetch(SpotifyWebAPI api)
public override IList<SpotifyImportListItemInfo> Fetch(SpotifyWebAPI api)
{
var result = new List<ImportListItemInfo>();
var result = new List<SpotifyImportListItemInfo>();
var savedAlbums = _spotifyProxy.GetSavedAlbums(this, api);
@ -62,7 +64,7 @@ namespace NzbDrone.Core.ImportLists.Spotify
return result;
}
private ImportListItemInfo ParseSavedAlbum(SavedAlbum savedAlbum)
private SpotifyImportListItemInfo ParseSavedAlbum(SavedAlbum savedAlbum)
{
var artistName = savedAlbum?.Album?.Artists?.FirstOrDefault()?.Name;
var albumName = savedAlbum?.Album?.Name;
@ -70,9 +72,11 @@ namespace NzbDrone.Core.ImportLists.Spotify
if (artistName.IsNotNullOrWhiteSpace() && albumName.IsNotNullOrWhiteSpace())
{
return new ImportListItemInfo {
return new SpotifyImportListItemInfo
{
Artist = artistName,
Album = albumName,
AlbumSpotifyId = savedAlbum?.Album?.Id,
ReleaseDate = ParseSpotifyDate(savedAlbum?.Album?.ReleaseDate, savedAlbum?.Album?.ReleaseDatePrecision)
};
}

Loading…
Cancel
Save