mirror of https://github.com/lidarr/Lidarr
Switched over to using Spotify API for meta data. This will require deleting DB to start using.
This commit is contained in:
parent
b481bc6e45
commit
a09d5d0b69
|
@ -8,7 +8,7 @@ namespace NzbDrone.Api.Music
|
|||
{
|
||||
public class AlbumResource
|
||||
{
|
||||
public int AlbumId { get; set; }
|
||||
public string AlbumId { get; set; }
|
||||
public string AlbumName { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
public int Year { get; set; }
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace NzbDrone.Api.Music
|
|||
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.ItunesId).GreaterThan(0).SetValidator(artistExistsValidator);
|
||||
PostValidator.RuleFor(s => s.SpotifyId).NotEqual("").SetValidator(artistExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
|
|
@ -19,9 +19,7 @@ namespace NzbDrone.Api.Music
|
|||
|
||||
//View Only
|
||||
public string ArtistName { get; set; }
|
||||
public int ItunesId { get; set; }
|
||||
//public List<AlternateTitleResource> AlternateTitles { get; set; }
|
||||
//public string SortTitle { get; set; }
|
||||
public string SpotifyId { get; set; }
|
||||
public string Overview { get; set; }
|
||||
|
||||
public int AlbumCount
|
||||
|
@ -30,7 +28,7 @@ namespace NzbDrone.Api.Music
|
|||
{
|
||||
if (Albums == null) return 0;
|
||||
|
||||
return Albums.Where(s => s.AlbumId > 0).Count(); // TODO: CHeck this condition
|
||||
return Albums.Where(s => s.AlbumId != "").Count(); // TODO: CHeck this condition
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +105,7 @@ namespace NzbDrone.Api.Music
|
|||
//FirstAired = resource.FirstAired,
|
||||
//LastInfoSync = resource.LastInfoSync,
|
||||
//SeriesType = resource.SeriesType,
|
||||
ItunesId = model.ItunesId,
|
||||
SpotifyId = model.SpotifyId,
|
||||
ArtistSlug = model.ArtistSlug,
|
||||
|
||||
RootFolderPath = model.RootFolderPath,
|
||||
|
@ -151,16 +149,8 @@ namespace NzbDrone.Api.Music
|
|||
|
||||
ArtistFolder = resource.ArtistFolder,
|
||||
Monitored = resource.Monitored,
|
||||
|
||||
//UseSceneNumbering = resource.UseSceneNumbering,
|
||||
//Runtime = resource.Runtime,
|
||||
//TvdbId = resource.TvdbId,
|
||||
//TvRageId = resource.TvRageId,
|
||||
//TvMazeId = resource.TvMazeId,
|
||||
//FirstAired = resource.FirstAired,
|
||||
//LastInfoSync = resource.LastInfoSync,
|
||||
//SeriesType = resource.SeriesType,
|
||||
ItunesId = resource.ItunesId,
|
||||
SpotifyId = resource.SpotifyId,
|
||||
ArtistSlug = resource.ArtistSlug,
|
||||
|
||||
RootFolderPath = resource.RootFolderPath,
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Common.Cloud
|
|||
Services = new HttpRequestBuilder("http://services.lidarr.tv/v1/")
|
||||
.CreateFactory();
|
||||
|
||||
Search = new HttpRequestBuilder("https://itunes.apple.com/{route}/")
|
||||
Search = new HttpRequestBuilder("https://api.spotify.com/v1/{route}/") // TODO: maybe use {version}
|
||||
.CreateFactory();
|
||||
|
||||
InternalSearch = new HttpRequestBuilder("https://itunes.apple.com/WebObjects/MZStore.woa/wa/{route}") //viewArtist or search
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace NzbDrone.Core.Datastore.Migration
|
|||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.TableForModel("Artist")
|
||||
.WithColumn("ItunesId").AsInt32().Unique()
|
||||
.WithColumn("SpotifyId").AsString().Nullable().Unique()
|
||||
.WithColumn("ArtistName").AsString().Unique()
|
||||
.WithColumn("ArtistSlug").AsString().Nullable() //.Unique()
|
||||
.WithColumn("CleanTitle").AsString().Nullable() // Do we need this?
|
||||
|
@ -37,8 +37,8 @@ namespace NzbDrone.Core.Datastore.Migration
|
|||
;
|
||||
|
||||
Create.TableForModel("Albums")
|
||||
.WithColumn("AlbumId").AsInt32()
|
||||
.WithColumn("ArtistId").AsInt32()
|
||||
.WithColumn("AlbumId").AsString().Unique()
|
||||
.WithColumn("ArtistId").AsInt32() // Should this be artistId (string)
|
||||
.WithColumn("Title").AsString()
|
||||
.WithColumn("Year").AsInt32()
|
||||
.WithColumn("Image").AsInt32()
|
||||
|
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Datastore.Migration
|
|||
|
||||
Create.TableForModel("Tracks")
|
||||
.WithColumn("ItunesTrackId").AsInt32().Unique()
|
||||
.WithColumn("AlbumId").AsInt32()
|
||||
.WithColumn("AlbumId").AsString()
|
||||
.WithColumn("ArtistsId").AsString().Nullable()
|
||||
.WithColumn("TrackNumber").AsInt32()
|
||||
.WithColumn("Title").AsString().Nullable()
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace NzbDrone.Core.Datastore
|
|||
.Relationships.AutoMapICollectionOrComplexProperties()
|
||||
.For("Tracks")
|
||||
.LazyLoad(condition: parent => parent.Id > 0,
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.ItunesTrackId == parent.Id).ToList())
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.SpotifyTrackId == parent.Id).ToList())
|
||||
.HasOne(file => file.Artist, file => file.AlbumId);
|
||||
|
||||
Mapper.Entity<Track>().RegisterModel("Tracks")
|
||||
|
|
|
@ -8,24 +8,24 @@ namespace NzbDrone.Core.Exceptions
|
|||
{
|
||||
public class ArtistNotFoundException : NzbDroneException
|
||||
{
|
||||
public int ItunesId { get; set; }
|
||||
public string SpotifyId { get; set; }
|
||||
|
||||
public ArtistNotFoundException(int itunesId)
|
||||
: base(string.Format("Series with iTunesId {0} was not found, it may have been removed from iTunes.", itunesId))
|
||||
public ArtistNotFoundException(string spotifyId)
|
||||
: base(string.Format("Artist with SpotifyId {0} was not found, it may have been removed from Spotify.", spotifyId))
|
||||
{
|
||||
ItunesId = itunesId;
|
||||
SpotifyId = spotifyId;
|
||||
}
|
||||
|
||||
public ArtistNotFoundException(int itunesId, string message, params object[] args)
|
||||
public ArtistNotFoundException(string spotifyId, string message, params object[] args)
|
||||
: base(message, args)
|
||||
{
|
||||
ItunesId = itunesId;
|
||||
SpotifyId = spotifyId;
|
||||
}
|
||||
|
||||
public ArtistNotFoundException(int itunesId, string message)
|
||||
public ArtistNotFoundException(string spotifyId, string message)
|
||||
: base(message)
|
||||
{
|
||||
ItunesId = itunesId;
|
||||
SpotifyId = spotifyId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
{
|
||||
public interface IProvideArtistInfo
|
||||
{
|
||||
Tuple<Artist, List<Track>> GetArtistInfo(int itunesId);
|
||||
Tuple<Artist, List<Track>> GetArtistInfo(string spotifyId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class AlbumInfoResource
|
||||
{
|
||||
public AlbumInfoResource()
|
||||
{
|
||||
|
||||
}
|
||||
public string AlbumType { get; set; } // Might need to make this a separate class
|
||||
public List<ArtistInfoResource> Artists { get; set; } // Will always be length of 1 unless a compilation
|
||||
public string Url { get; set; } // Link to the endpoint api to give full info for this object
|
||||
public string Id { get; set; } // This is a unique Album ID. Needed for all future API calls
|
||||
public List<ImageResource> Images { get; set; }
|
||||
public string Name { get; set; } // In case of a takedown, this may be empty
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class ArtistInfoResource
|
||||
{
|
||||
public ArtistInfoResource() { }
|
||||
|
||||
public List<string> Genres { get; set; }
|
||||
public string AristUrl { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<ImageResource> Images { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
// We may need external_urls.spotify to external linking...
|
||||
}
|
||||
}
|
|
@ -5,61 +5,25 @@ using System.Text;
|
|||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class StorePlatformDataResource
|
||||
|
||||
public class AristResultResource
|
||||
{
|
||||
public StorePlatformDataResource() { }
|
||||
public ArtistInfoResource Artist { get; set; }
|
||||
//public Lockup lockup { get; set; }
|
||||
}
|
||||
|
||||
public class ArtistInfoResource
|
||||
{
|
||||
public ArtistInfoResource() { }
|
||||
public Dictionary<int, ArtistInfoResource> Results { get; set; }
|
||||
|
||||
public bool HasArtistBio { get; set; }
|
||||
|
||||
public string url { get; set; }
|
||||
public string shortUrl { get; set; }
|
||||
|
||||
public List<string> artistContemporaries { get; set; }
|
||||
public List<string> genreNames { get; set; }
|
||||
public bool hasSocialPosts { get; set; }
|
||||
public string artistBio { get; set; }
|
||||
public bool isGroup { get; set; }
|
||||
public string id { get; set; }
|
||||
public string bornOrFormed { get; set; }
|
||||
public string name { get; set; }
|
||||
public string latestAlbumContentId { get; set; }
|
||||
public string nameRaw { get; set; }
|
||||
|
||||
//public string kind { get; set; }
|
||||
//public List<Gallery> gallery { get; set; }
|
||||
//public List<Genre> genres { get; set; }
|
||||
public List<object> artistInfluencers { get; set; }
|
||||
public List<object> artistFollowers { get; set; }
|
||||
//public string umcArtistImageUrl { get; set; }
|
||||
}
|
||||
|
||||
public class AlbumResource
|
||||
{
|
||||
public AlbumResource()
|
||||
public AristResultResource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public string ArtistName { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
public string CollectionName { get; set; }
|
||||
public int CollectionId { get; set; }
|
||||
public string PrimaryGenreName { get; set; }
|
||||
public string ArtworkUrl100 { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string CollectionExplicitness { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public string Copyright { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public List<ArtistInfoResource> Items { get; set; }
|
||||
}
|
||||
|
||||
public class AlbumResultResource
|
||||
{
|
||||
public AlbumResultResource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public List<AlbumInfoResource> Items { get; set; }
|
||||
}
|
||||
|
||||
public class ArtistResource
|
||||
|
@ -69,10 +33,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||
|
||||
}
|
||||
|
||||
public int ResultCount { get; set; }
|
||||
public List<AlbumResource> Results { get; set; }
|
||||
//public string ArtistName { get; set; }
|
||||
//public List<AlbumResource> Albums { get; set; }
|
||||
public StorePlatformDataResource StorePlatformData { get; set; }
|
||||
public AristResultResource Artists { get; set; }
|
||||
public AristResultResource Albums { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||
public class ImageResource
|
||||
{
|
||||
public string CoverType { get; set; }
|
||||
|
||||
// Spotify Mapping
|
||||
public string Url { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int Width { get; set; }
|
||||
}
|
||||
}
|
|
@ -22,13 +22,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
private readonly Logger _logger;
|
||||
|
||||
private readonly IHttpRequestBuilderFactory _requestBuilder;
|
||||
private readonly IHttpRequestBuilderFactory _internalRequestBuilder;
|
||||
|
||||
public SkyHookProxy(IHttpClient httpClient, ILidarrCloudRequestBuilder requestBuilder, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_requestBuilder = requestBuilder.Search;
|
||||
_internalRequestBuilder = requestBuilder.InternalSearch;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -67,153 +65,97 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
public List<Series> SearchForNewSeries(string title)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lowerTitle = title.ToLowerInvariant();
|
||||
Console.WriteLine("Searching for " + lowerTitle);
|
||||
|
||||
//if (lowerTitle.StartsWith("tvdb:") || lowerTitle.StartsWith("tvdbid:"))
|
||||
//{
|
||||
// var slug = lowerTitle.Split(':')[1].Trim();
|
||||
|
||||
// int tvdbId;
|
||||
|
||||
// if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace) || !int.TryParse(slug, out tvdbId) || tvdbId <= 0)
|
||||
// {
|
||||
// return new List<Series>();
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// return new List<Series> { GetSeriesInfo(tvdbId).Item1 };
|
||||
// }
|
||||
// catch (SeriesNotFoundException)
|
||||
// {
|
||||
// return new List<Series>();
|
||||
// }
|
||||
//}
|
||||
|
||||
// Majora: Temporarily, use iTunes to test.
|
||||
var httpRequest = _requestBuilder.Create()
|
||||
.AddQueryParam("entity", "album")
|
||||
.AddQueryParam("term", title.ToLower().Trim())
|
||||
.Build();
|
||||
|
||||
|
||||
|
||||
Console.WriteLine("httpRequest: ", httpRequest);
|
||||
|
||||
var httpResponse = _httpClient.Get<List<ShowResource>>(httpRequest);
|
||||
|
||||
//Console.WriteLine("Response: ", httpResponse.GetType());
|
||||
//_logger.Info("Response: ", httpResponse.Resource.ResultCount);
|
||||
|
||||
//_logger.Info("HTTP Response: ", httpResponse.Resource.ResultCount);
|
||||
var tempList = new List<Series>();
|
||||
var tempSeries = new Series();
|
||||
tempSeries.Title = "AFI";
|
||||
tempList.Add(tempSeries);
|
||||
return tempList;
|
||||
|
||||
return httpResponse.Resource.SelectList(MapSeries);
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
throw new SkyHookException("Search for '{0}' failed. Unable to communicate with SkyHook.", title);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, ex.Message);
|
||||
throw new SkyHookException("Search for '{0}' failed. Invalid response received from SkyHook.", title);
|
||||
}
|
||||
// TODO: Remove this API
|
||||
var tempList = new List<Series>();
|
||||
var tempSeries = new Series();
|
||||
tempSeries.Title = "AFI";
|
||||
tempList.Add(tempSeries);
|
||||
return tempList;
|
||||
}
|
||||
|
||||
//public Artist GetArtistInfo(int itunesId)
|
||||
//{
|
||||
// Console.WriteLine("[GetArtistInfo] id:" + itunesId);
|
||||
// //https://itunes.apple.com/lookup?id=909253
|
||||
// //var httpRequest = _requestBuilder.Create()
|
||||
// // .SetSegment("route", "lookup")
|
||||
// // .AddQueryParam("id", itunesId.ToString())
|
||||
// // .Build();
|
||||
|
||||
// // TODO: Add special header, add Overview to Artist model
|
||||
// var httpRequest = _requestBuilder.Create()
|
||||
// .SetSegment("route", "viewArtist")
|
||||
// .AddQueryParam("id", itunesId.ToString())
|
||||
// .Build();
|
||||
// httpRequest.Headers.Add("X-Apple-Store-Front", "143459-2,32 t:music3");
|
||||
|
||||
// httpRequest.AllowAutoRedirect = true;
|
||||
// httpRequest.SuppressHttpError = true;
|
||||
|
||||
// var httpResponse = _httpClient.Get<ArtistResource>(httpRequest);
|
||||
|
||||
// if (httpResponse.HasHttpError)
|
||||
// {
|
||||
// if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
||||
// {
|
||||
// throw new ArtistNotFoundException(itunesId);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new HttpException(httpRequest, httpResponse);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Console.WriteLine("GetArtistInfo, GetArtistInfo");
|
||||
// return MapArtists(httpResponse.Resource)[0];
|
||||
//}
|
||||
|
||||
public Tuple<Artist, List<Track>> GetArtistInfo(int itunesId)
|
||||
public Tuple<Artist, List<Track>> GetArtistInfo(string spotifyId)
|
||||
{
|
||||
// TODO: [GetArtistInfo]: This needs to return a set of tracks from iTunes.
|
||||
// This call is expected to return information about an artist and the tracks that make up said artist.
|
||||
// To do this, we need 2-3 API calls. 1st is to gather information about the artist and the albums the artist has. This is https://itunes.apple.com/search?entity=album&id=itunesId
|
||||
// Next call is to populate the overview field and calls the internal API
|
||||
// Finally, we need to, for each album, get all tracks, which means calling this N times: https://itunes.apple.com/search?entity=musicTrack&term=artistName (id will not work)
|
||||
_logger.Debug("Getting Artist with iTunesID of {0}", itunesId);
|
||||
var httpRequest1 = _requestBuilder.Create()
|
||||
.SetSegment("route", "lookup")
|
||||
.AddQueryParam("id", itunesId.ToString())
|
||||
|
||||
_logger.Debug("Getting Artist with SpotifyId of {0}", spotifyId);
|
||||
|
||||
///v1/albums/{id}
|
||||
//
|
||||
|
||||
// We need to perform a direct lookup of the artist
|
||||
var httpRequest = _requestBuilder.Create()
|
||||
.SetSegment("route", "artists/" + spotifyId)
|
||||
//.SetSegment("route", "search")
|
||||
//.AddQueryParam("type", "artist,album")
|
||||
//.AddQueryParam("q", spotifyId.ToString())
|
||||
.Build();
|
||||
|
||||
var httpRequest2 = _internalRequestBuilder.Create()
|
||||
.SetSegment("route", "viewArtist")
|
||||
.AddQueryParam("id", itunesId.ToString())
|
||||
.Build();
|
||||
httpRequest2.Headers.Add("X-Apple-Store-Front", "143459-2,32 t:music3");
|
||||
httpRequest2.Headers.ContentType = "application/json";
|
||||
|
||||
|
||||
httpRequest1.AllowAutoRedirect = true;
|
||||
httpRequest1.SuppressHttpError = true;
|
||||
httpRequest.AllowAutoRedirect = true;
|
||||
httpRequest.SuppressHttpError = true;
|
||||
|
||||
var httpResponse = _httpClient.Get<ArtistResource>(httpRequest1);
|
||||
var httpResponse = _httpClient.Get<ArtistInfoResource>(httpRequest);
|
||||
|
||||
|
||||
if (httpResponse.HasHttpError)
|
||||
{
|
||||
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
throw new ArtistNotFoundException(itunesId);
|
||||
throw new ArtistNotFoundException(spotifyId);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpException(httpRequest1, httpResponse);
|
||||
throw new HttpException(httpRequest, httpResponse);
|
||||
}
|
||||
}
|
||||
|
||||
List<Artist> artists = MapArtists(httpResponse.Resource);
|
||||
List<Artist> newArtists = new List<Artist>(artists.Count);
|
||||
int count = 0;
|
||||
foreach (var artist in artists)
|
||||
Artist artist = new Artist();
|
||||
artist.ArtistName = httpResponse.Resource.Name;
|
||||
artist.SpotifyId = httpResponse.Resource.Id;
|
||||
artist.Genres = httpResponse.Resource.Genres;
|
||||
//Artist artist = MapArtists(httpResponse.Resource)[0];
|
||||
|
||||
|
||||
artist = MapAlbums(artist);
|
||||
|
||||
|
||||
// TODO: implement tracks api call
|
||||
return new Tuple<Artist, List<Track>>(artist, new List<Track>());
|
||||
}
|
||||
|
||||
private Artist MapAlbums(Artist artist)
|
||||
{
|
||||
|
||||
// Find all albums for the artist and all tracks for said album
|
||||
///v1/artists/{id}/albums
|
||||
var httpRequest = _requestBuilder.Create()
|
||||
.SetSegment("route", "artists/" + artist.SpotifyId + "/albums")
|
||||
.Build();
|
||||
httpRequest.AllowAutoRedirect = true;
|
||||
httpRequest.SuppressHttpError = true;
|
||||
|
||||
var httpResponse = _httpClient.Get<AlbumResultResource>(httpRequest);
|
||||
|
||||
if (httpResponse.HasHttpError)
|
||||
{
|
||||
newArtists.Add(AddOverview(artist));
|
||||
count++;
|
||||
throw new HttpException(httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
// I don't know how we are getting tracks from iTunes yet.
|
||||
return new Tuple<Artist, List<Track>>(newArtists[0], new List<Track>());
|
||||
List<Album> albums = new List<Album>();
|
||||
foreach(var albumResource in httpResponse.Resource.Items)
|
||||
{
|
||||
Album album = new Album();
|
||||
album.AlbumId = albumResource.Id;
|
||||
album.Title = albumResource.Name;
|
||||
album.ArtworkUrl = albumResource.Images[0].Url;
|
||||
albums.Add(album);
|
||||
}
|
||||
|
||||
// TODO: We now need to get all tracks for each album
|
||||
|
||||
artist.Albums = albums;
|
||||
return artist;
|
||||
}
|
||||
|
||||
public List<Artist> SearchForNewArtist(string title)
|
||||
|
@ -227,16 +169,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
{
|
||||
var slug = lowerTitle.Split(':')[1].Trim();
|
||||
|
||||
int itunesId;
|
||||
|
||||
if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace) || !int.TryParse(slug, out itunesId) || itunesId <= 0)
|
||||
if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace))
|
||||
{
|
||||
return new List<Artist>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new List<Artist> { GetArtistInfo(itunesId).Item1 };
|
||||
return new List<Artist> { GetArtistInfo(slug).Item1 };
|
||||
}
|
||||
catch (ArtistNotFoundException)
|
||||
{
|
||||
|
@ -246,8 +186,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
var httpRequest = _requestBuilder.Create()
|
||||
.SetSegment("route", "search")
|
||||
.AddQueryParam("entity", "album")
|
||||
.AddQueryParam("term", title.ToLower().Trim())
|
||||
.AddQueryParam("type", "artist,album")
|
||||
.AddQueryParam("q", title.ToLower().Trim())
|
||||
.Build();
|
||||
|
||||
|
||||
|
@ -256,16 +196,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
|
||||
List<Artist> artists = MapArtists(httpResponse.Resource);
|
||||
List<Artist> newArtists = new List<Artist>(artists.Count);
|
||||
int count = 0;
|
||||
foreach (var artist in artists)
|
||||
{
|
||||
newArtists.Add(AddOverview(artist));
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
return newArtists;
|
||||
return artists;
|
||||
}
|
||||
catch (HttpException)
|
||||
{
|
||||
|
@ -278,77 +210,52 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
}
|
||||
}
|
||||
|
||||
private Artist AddOverview(Artist artist)
|
||||
{
|
||||
var httpRequest = _internalRequestBuilder.Create()
|
||||
.SetSegment("route", "viewArtist")
|
||||
.AddQueryParam("id", artist.ItunesId.ToString())
|
||||
.Build();
|
||||
httpRequest.Headers.Add("X-Apple-Store-Front", "143459-2,32 t:music3");
|
||||
httpRequest.Headers.ContentType = "application/json";
|
||||
var httpResponse = _httpClient.Get<ArtistResource>(httpRequest);
|
||||
|
||||
if (!httpResponse.HasHttpError)
|
||||
{
|
||||
artist.Overview = httpResponse.Resource.StorePlatformData.Artist.Results[artist.ItunesId].artistBio;
|
||||
}
|
||||
|
||||
return artist;
|
||||
}
|
||||
|
||||
private Artist MapArtistInfo(ArtistInfoResource resource)
|
||||
{
|
||||
// This expects ArtistInfoResource, thus just need to populate one artist
|
||||
Artist artist = new Artist();
|
||||
artist.Overview = resource.artistBio;
|
||||
artist.ArtistName = resource.name;
|
||||
foreach(var genre in resource.genreNames)
|
||||
{
|
||||
artist.Genres.Add(genre);
|
||||
}
|
||||
//artist.Overview = resource.artistBio;
|
||||
//artist.ArtistName = resource.name;
|
||||
//foreach(var genre in resource.genreNames)
|
||||
//{
|
||||
// artist.Genres.Add(genre);
|
||||
//}
|
||||
|
||||
return artist;
|
||||
}
|
||||
|
||||
private List<Artist> MapArtists(ArtistResource resource)
|
||||
{
|
||||
Album tempAlbum;
|
||||
|
||||
|
||||
List<Artist> artists = new List<Artist>();
|
||||
foreach (var album in resource.Results)
|
||||
foreach(var artistResource in resource.Artists.Items)
|
||||
{
|
||||
int index = artists.FindIndex(a => a.ItunesId == album.ArtistId);
|
||||
tempAlbum = MapAlbum(album);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
artists[index].Albums.Add(tempAlbum);
|
||||
}
|
||||
else
|
||||
{
|
||||
Artist tempArtist = new Artist();
|
||||
tempArtist.ItunesId = album.ArtistId;
|
||||
tempArtist.ArtistName = album.ArtistName;
|
||||
tempArtist.Genres.Add(album.PrimaryGenreName);
|
||||
tempArtist.Albums.Add(tempAlbum);
|
||||
artists.Add(tempArtist);
|
||||
}
|
||||
|
||||
Artist artist = new Artist();
|
||||
artist.ArtistName = artistResource.Name;
|
||||
artist.SpotifyId = artistResource.Id;
|
||||
artist.Genres = artistResource.Genres;
|
||||
//artist.ArtistSlug = a//TODO implement artistSlug mapping;
|
||||
artists.Add(artist);
|
||||
}
|
||||
|
||||
// Maybe? Get all the albums for said artist
|
||||
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
private Album MapAlbum(AlbumResource albumQuery)
|
||||
{
|
||||
Album album = new Album();
|
||||
//private Album MapAlbum(AlbumResource albumQuery)
|
||||
//{
|
||||
// Album album = new Album();
|
||||
|
||||
album.AlbumId = albumQuery.CollectionId;
|
||||
album.Title = albumQuery.CollectionName;
|
||||
album.Year = albumQuery.ReleaseDate.Year;
|
||||
album.ArtworkUrl = albumQuery.ArtworkUrl100;
|
||||
album.Explicitness = albumQuery.CollectionExplicitness;
|
||||
return album;
|
||||
}
|
||||
// album.AlbumId = albumQuery.CollectionId;
|
||||
// album.Title = albumQuery.CollectionName;
|
||||
// album.Year = albumQuery.ReleaseDate.Year;
|
||||
// album.ArtworkUrl = albumQuery.ArtworkUrl100;
|
||||
// album.Explicitness = albumQuery.CollectionExplicitness;
|
||||
// return album;
|
||||
//}
|
||||
|
||||
private static Series MapSeries(ShowResource show)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
if (string.IsNullOrWhiteSpace(newArtist.Path))
|
||||
{
|
||||
var folderName = newArtist.ArtistName;// _fileNameBuilder.GetArtistFolder(newArtist);
|
||||
var folderName = newArtist.ArtistName;// TODO: _fileNameBuilder.GetArtistFolder(newArtist);
|
||||
newArtist.Path = Path.Combine(newArtist.RootFolderPath, folderName);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Music
|
|||
throw new ValidationException(validationResult.Errors);
|
||||
}
|
||||
|
||||
_logger.Info("Adding Series {0} Path: [{1}]", newArtist, newArtist.Path);
|
||||
_logger.Info("Adding Artist {0} Path: [{1}]", newArtist, newArtist.Path);
|
||||
_artistService.AddArtist(newArtist);
|
||||
|
||||
return newArtist;
|
||||
|
@ -75,15 +75,15 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
try
|
||||
{
|
||||
tuple = _artistInfo.GetArtistInfo(newArtist.ItunesId);
|
||||
tuple = _artistInfo.GetArtistInfo(newArtist.SpotifyId);
|
||||
}
|
||||
catch (SeriesNotFoundException)
|
||||
{
|
||||
_logger.Error("iTunesId {1} was not found, it may have been removed from iTunes.", newArtist.ItunesId);
|
||||
_logger.Error("SpotifyId {1} was not found, it may have been removed from Spotify.", newArtist.SpotifyId);
|
||||
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new ValidationFailure("iTunesId", "An artist with this ID was not found", newArtist.ItunesId)
|
||||
new ValidationFailure("SpotifyId", "An artist with this ID was not found", newArtist.SpotifyId)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace NzbDrone.Core.Music
|
|||
Images = new List<MediaCover.MediaCover>();
|
||||
}
|
||||
|
||||
public int AlbumId { get; set; }
|
||||
public string AlbumId { get; set; }
|
||||
public string Title { get; set; } // NOTE: This should be CollectionName in API
|
||||
public int Year { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
}
|
||||
|
||||
public int ItunesId { get; set; }
|
||||
public string SpotifyId { get; set; }
|
||||
public string ArtistName { get; set; }
|
||||
public string ArtistSlug { get; set; }
|
||||
public string CleanTitle { get; set; }
|
||||
|
@ -47,13 +47,13 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}][{1}]", ItunesId, ArtistName.NullSafe());
|
||||
return string.Format("[{0}][{1}]", SpotifyId, ArtistName.NullSafe());
|
||||
}
|
||||
|
||||
public void ApplyChanges(Artist otherArtist)
|
||||
{
|
||||
|
||||
ItunesId = otherArtist.ItunesId;
|
||||
SpotifyId = otherArtist.SpotifyId;
|
||||
ArtistName = otherArtist.ArtistName;
|
||||
ArtistSlug = otherArtist.ArtistSlug;
|
||||
CleanTitle = otherArtist.CleanTitle;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Core.Music
|
|||
{
|
||||
bool ArtistPathExists(string path);
|
||||
Artist FindByName(string cleanTitle);
|
||||
Artist FindByItunesId(int iTunesId);
|
||||
Artist FindById(string spotifyId);
|
||||
}
|
||||
|
||||
public class ArtistRepository : BasicRepository<Artist>, IArtistRepository
|
||||
|
@ -24,9 +24,9 @@ namespace NzbDrone.Core.Music
|
|||
return Query.Where(c => c.Path == path).Any();
|
||||
}
|
||||
|
||||
public Artist FindByItunesId(int iTunesId)
|
||||
public Artist FindById(string spotifyId)
|
||||
{
|
||||
return Query.Where(s => s.ItunesId == iTunesId).SingleOrDefault();
|
||||
return Query.Where(s => s.SpotifyId == spotifyId).SingleOrDefault();
|
||||
}
|
||||
|
||||
public Artist FindByName(string cleanName)
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Core.Music
|
|||
Artist GetArtist(int artistId);
|
||||
List<Artist> GetArtists(IEnumerable<int> artistIds);
|
||||
Artist AddArtist(Artist newArtist);
|
||||
Artist FindByItunesId(int itunesId);
|
||||
Artist FindById(string spotifyId);
|
||||
Artist FindByName(string title);
|
||||
Artist FindByTitleInexact(string title);
|
||||
void DeleteArtist(int artistId, bool deleteFiles);
|
||||
|
@ -69,9 +69,9 @@ namespace NzbDrone.Core.Music
|
|||
_eventAggregator.PublishEvent(new ArtistDeletedEvent(artist, deleteFiles));
|
||||
}
|
||||
|
||||
public Artist FindByItunesId(int itunesId)
|
||||
public Artist FindById(string spotifyId)
|
||||
{
|
||||
return _artistRepository.FindByItunesId(itunesId);
|
||||
return _artistRepository.FindById(spotifyId);
|
||||
}
|
||||
|
||||
public Artist FindByName(string title)
|
||||
|
@ -114,7 +114,7 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
if (storedAlbum != null && album.Monitored != storedAlbum.Monitored)
|
||||
{
|
||||
_trackService.SetTrackMonitoredByAlbum(artist.Id, album.AlbumId, album.Monitored);
|
||||
_trackService.SetTrackMonitoredByAlbum(artist.SpotifyId, album.AlbumId, album.Monitored);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,20 +52,20 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
try
|
||||
{
|
||||
tuple = _artistInfo.GetArtistInfo(artist.ItunesId);
|
||||
tuple = _artistInfo.GetArtistInfo(artist.SpotifyId);
|
||||
}
|
||||
catch (ArtistNotFoundException)
|
||||
{
|
||||
_logger.Error("Artist '{0}' (itunesid {1}) was not found, it may have been removed from iTunes.", artist.ArtistName, artist.ItunesId);
|
||||
_logger.Error("Artist '{0}' (SpotifyId {1}) was not found, it may have been removed from Spotify.", artist.ArtistName, artist.SpotifyId);
|
||||
return;
|
||||
}
|
||||
|
||||
var artistInfo = tuple.Item1;
|
||||
|
||||
if (artist.ItunesId != artistInfo.ItunesId)
|
||||
if (artist.SpotifyId != artistInfo.SpotifyId)
|
||||
{
|
||||
_logger.Warn("Artist '{0}' (itunes {1}) was replaced with '{2}' (itunes {3}), because the original was a duplicate.", artist.ArtistName, artist.ItunesId, artistInfo.ArtistName, artistInfo.ItunesId);
|
||||
artist.ItunesId = artistInfo.ItunesId;
|
||||
_logger.Warn("Artist '{0}' (SpotifyId {1}) was replaced with '{2}' (SpotifyId {3}), because the original was a duplicate.", artist.ArtistName, artist.SpotifyId, artistInfo.ArtistName, artistInfo.SpotifyId);
|
||||
artist.SpotifyId = artistInfo.SpotifyId;
|
||||
}
|
||||
|
||||
artist.ArtistName = artistInfo.ArtistName;
|
||||
|
@ -114,7 +114,7 @@ namespace NzbDrone.Core.Music
|
|||
// continue;
|
||||
//}
|
||||
|
||||
_logger.Debug("New album ({0}) for artist: [{1}] {2}, setting monitored to true", album.Title, artist.ItunesId, artist.ArtistName);
|
||||
_logger.Debug("New album ({0}) for artist: [{1}] {2}, setting monitored to true", album.Title, artist.SpotifyId, artist.ArtistName);
|
||||
album.Monitored = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Music
|
|||
var successCount = 0;
|
||||
var failCount = 0;
|
||||
|
||||
var existingTracks = _trackService.GetTrackByArtist(artist.ItunesId);
|
||||
var existingTracks = _trackService.GetTrackByArtist(artist.SpotifyId);
|
||||
var albums = artist.Albums;
|
||||
|
||||
var updateList = new List<Track>();
|
||||
|
@ -57,7 +57,7 @@ namespace NzbDrone.Core.Music
|
|||
trackToUpdate.Monitored = GetMonitoredStatus(track, albums);
|
||||
newList.Add(trackToUpdate);
|
||||
}
|
||||
trackToUpdate.ArtistId = artist.ItunesId; // TODO: Ensure LazyLoaded<Artist> field gets updated.
|
||||
trackToUpdate.ArtistId = artist.SpotifyId; // TODO: Ensure LazyLoaded<Artist> field gets updated.
|
||||
trackToUpdate.TrackNumber = track.TrackNumber;
|
||||
trackToUpdate.Title = track.Title ?? "Unknown";
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
public const string RELEASE_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
public int ItunesTrackId { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public int SpotifyTrackId { get; set; }
|
||||
public string AlbumId { get; set; }
|
||||
public LazyLoaded<Artist> Artist { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
public string ArtistId { get; set; }
|
||||
public int CompilationId { get; set; }
|
||||
public bool Compilation { get; set; }
|
||||
public int TrackNumber { get; set; }
|
||||
|
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}]{1}", ItunesTrackId, Title.NullSafe());
|
||||
return string.Format("[{0}]{1}", SpotifyTrackId, Title.NullSafe());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ namespace NzbDrone.Core.Music
|
|||
{
|
||||
Track GetTrack(int id);
|
||||
List<Track> GetTracks(IEnumerable<int> ids);
|
||||
Track FindTrack(int artistId, int albumId, int trackNumber);
|
||||
Track FindTrackByTitle(int artistId, int albumId, string releaseTitle);
|
||||
List<Track> GetTrackByArtist(int artistId);
|
||||
List<Track> GetTracksByAblum(int artistId, int albumId);
|
||||
List<Track> GetTracksByAblumTitle(int artistId, string albumTitle);
|
||||
List<Track> TracksWithFiles(int artistId);
|
||||
Track FindTrack(string artistId, string albumId, int trackNumber);
|
||||
Track FindTrackByTitle(string artistId, string albumId, string releaseTitle);
|
||||
List<Track> GetTrackByArtist(string artistId);
|
||||
List<Track> GetTracksByAlbum(string artistId, string albumId);
|
||||
List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle);
|
||||
List<Track> TracksWithFiles(string artistId);
|
||||
PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
||||
List<Track> GeTracksByFileId(int trackFileId);
|
||||
void UpdateTrack(Track track);
|
||||
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.Music
|
|||
void InsertMany(List<Track> tracks);
|
||||
void UpdateMany(List<Track> tracks);
|
||||
void DeleteMany(List<Track> tracks);
|
||||
void SetTrackMonitoredByAlbum(int artistId, int albumId, bool monitored);
|
||||
void SetTrackMonitoredByAlbum(string artistId, string albumId, bool monitored);
|
||||
}
|
||||
|
||||
public class TrackService : ITrackService
|
||||
|
@ -34,12 +34,12 @@ namespace NzbDrone.Core.Music
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Track FindTrack(int artistId, int albumId, int trackNumber)
|
||||
public Track FindTrack(string artistId, string albumId, int trackNumber)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Track FindTrackByTitle(int artistId, int albumId, string releaseTitle)
|
||||
public Track FindTrackByTitle(string artistId, string albumId, string releaseTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ namespace NzbDrone.Core.Music
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> GetTrackByArtist(int artistId)
|
||||
public List<Track> GetTrackByArtist(string artistId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ namespace NzbDrone.Core.Music
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByAblum(int artistId, int albumId)
|
||||
public List<Track> GetTracksByAlbum(string artistId, string albumId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByAblumTitle(int artistId, string albumTitle)
|
||||
public List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -84,12 +84,12 @@ namespace NzbDrone.Core.Music
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetTrackMonitoredByAlbum(int artistId, int albumId, bool monitored)
|
||||
public void SetTrackMonitoredByAlbum(string artistId, string albumId, bool monitored)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> TracksWithFiles(int artistId)
|
||||
public List<Track> TracksWithFiles(string artistId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -815,6 +815,8 @@
|
|||
<Compile Include="Messaging\IProcessMessage.cs" />
|
||||
<Compile Include="MetadataSource\IProvideArtistInfo.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ActorResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\AlbumInfoResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ArtistInfoResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ArtistResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\EpisodeResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ImageResource.cs" />
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||
public MediaInfoModel MediaInfo { get; set; }
|
||||
public bool ExistingFile { get; set; }
|
||||
|
||||
public int Album
|
||||
public string Album
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsSpecial => Album == 0;
|
||||
public bool IsSpecial => Album != "";
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace NzbDrone.Core.Validation.Paths
|
|||
private readonly IArtistService _artistService;
|
||||
|
||||
public ArtistExistsValidator(IArtistService artistService)
|
||||
: base("This artist has already been added")
|
||||
: base("This artist has already been added.")
|
||||
{
|
||||
_artistService = artistService;
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ namespace NzbDrone.Core.Validation.Paths
|
|||
{
|
||||
if (context.PropertyValue == null) return true;
|
||||
|
||||
var itunesId = Convert.ToInt32(context.PropertyValue.ToString());
|
||||
|
||||
return (!_artistService.GetAllArtists().Exists(s => s.ItunesId == itunesId));
|
||||
return (!_artistService.GetAllArtists().Exists(s => s.SpotifyId == context.PropertyValue.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,12 +223,12 @@ var view = Marionette.ItemView.extend({
|
|||
self.close();
|
||||
|
||||
Messenger.show({
|
||||
message : 'Added: ' + self.model.get('title'),
|
||||
message : 'Added: ' + self.model.get('artistName'),
|
||||
actions : {
|
||||
goToSeries : {
|
||||
label : 'Go to Artist',
|
||||
action : function() {
|
||||
Backbone.history.navigate('/artist/' + self.model.get('titleSlug'), { trigger : true });
|
||||
Backbone.history.navigate('/artist/' + self.model.get('artistSlug'), { trigger : true });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue