mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
Album Repo Work
Adds Album Repo (Need to Update Album API), Gets Tracks working with new Schema, Fixes Albums Saving to DB
This commit is contained in:
parent
15b70ede7c
commit
a8ac1f3adc
25 changed files with 549 additions and 74 deletions
|
@ -11,7 +11,7 @@ namespace NzbDrone.Api.Music
|
||||||
public string AlbumId { get; set; }
|
public string AlbumId { get; set; }
|
||||||
public string AlbumName { get; set; }
|
public string AlbumName { get; set; }
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
public int Year { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
public string ArtworkUrl { get; set; }
|
public string ArtworkUrl { get; set; }
|
||||||
|
|
||||||
|
@ -25,12 +25,12 @@ namespace NzbDrone.Api.Music
|
||||||
|
|
||||||
return new AlbumResource
|
return new AlbumResource
|
||||||
{
|
{
|
||||||
AlbumId = model.AlbumId,
|
AlbumId = model.ForeignAlbumId,
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
Year = model.Year,
|
ReleaseDate = model.ReleaseDate,
|
||||||
AlbumName = model.Title,
|
AlbumName = model.Title,
|
||||||
Genres = model.Genres,
|
Genres = model.Genres,
|
||||||
ArtworkUrl = model.ArtworkUrl
|
//ArtworkUrl = model.ArtworkUrl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@ namespace NzbDrone.Api.Music
|
||||||
|
|
||||||
return new Album
|
return new Album
|
||||||
{
|
{
|
||||||
AlbumId = resource.AlbumId,
|
ForeignAlbumId = resource.AlbumId,
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
Year = resource.Year,
|
ReleaseDate = resource.ReleaseDate,
|
||||||
Title = resource.AlbumName,
|
Title = resource.AlbumName,
|
||||||
Genres = resource.Genres,
|
Genres = resource.Genres,
|
||||||
ArtworkUrl = resource.ArtworkUrl
|
//ArtworkUrl = resource.ArtworkUrl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,14 +42,13 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
Create.TableForModel("Albums")
|
Create.TableForModel("Albums")
|
||||||
.WithColumn("ForeignAlbumId").AsString().Unique()
|
.WithColumn("ForeignAlbumId").AsString().Unique()
|
||||||
.WithColumn("ArtistId").AsInt32()
|
.WithColumn("ArtistId").AsInt32()
|
||||||
.WithColumn("MBId").AsString().Indexed()
|
.WithColumn("MBId").AsString().Nullable().Indexed()
|
||||||
.WithColumn("AMId").AsString().Nullable()
|
.WithColumn("AMId").AsString().Nullable()
|
||||||
.WithColumn("TADBId").AsInt32().Indexed()
|
.WithColumn("TADBId").AsInt32().Nullable().Indexed()
|
||||||
.WithColumn("DiscogsId").AsInt32().Nullable()
|
.WithColumn("DiscogsId").AsInt32().Nullable()
|
||||||
.WithColumn("Title").AsString()
|
.WithColumn("Title").AsString()
|
||||||
.WithColumn("TitleSlug").AsString().Nullable().Unique()
|
.WithColumn("TitleSlug").AsString().Nullable().Unique()
|
||||||
.WithColumn("CleanTitle").AsString().Indexed()
|
.WithColumn("CleanTitle").AsString().Indexed()
|
||||||
.WithColumn("Status").AsInt32()
|
|
||||||
.WithColumn("Overview").AsString().Nullable()
|
.WithColumn("Overview").AsString().Nullable()
|
||||||
.WithColumn("Images").AsString()
|
.WithColumn("Images").AsString()
|
||||||
.WithColumn("Path").AsString().Indexed()
|
.WithColumn("Path").AsString().Indexed()
|
||||||
|
@ -71,7 +70,7 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
.WithColumn("ForeignTrackId").AsString().Unique()
|
.WithColumn("ForeignTrackId").AsString().Unique()
|
||||||
.WithColumn("ArtistId").AsInt32().Indexed()
|
.WithColumn("ArtistId").AsInt32().Indexed()
|
||||||
.WithColumn("AlbumId").AsInt32()
|
.WithColumn("AlbumId").AsInt32()
|
||||||
.WithColumn("MBId").AsString().Indexed()
|
.WithColumn("MBId").AsString().Nullable().Indexed()
|
||||||
.WithColumn("TrackNumber").AsInt32()
|
.WithColumn("TrackNumber").AsInt32()
|
||||||
.WithColumn("Title").AsString().Nullable()
|
.WithColumn("Title").AsString().Nullable()
|
||||||
.WithColumn("Explicit").AsBoolean()
|
.WithColumn("Explicit").AsBoolean()
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Datastore
|
||||||
.Relationship()
|
.Relationship()
|
||||||
.HasOne(a => a.Profile, a => a.ProfileId);
|
.HasOne(a => a.Profile, a => a.ProfileId);
|
||||||
|
|
||||||
Mapper.Entity<Album>().RegisterModel("Album");
|
Mapper.Entity<Album>().RegisterModel("Albums");
|
||||||
|
|
||||||
Mapper.Entity<TrackFile>().RegisterModel("TrackFiles")
|
Mapper.Entity<TrackFile>().RegisterModel("TrackFiles")
|
||||||
.Ignore(f => f.Path)
|
.Ignore(f => f.Path)
|
||||||
|
|
|
@ -6,6 +6,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
{
|
{
|
||||||
public interface IProvideArtistInfo
|
public interface IProvideArtistInfo
|
||||||
{
|
{
|
||||||
Tuple<Artist, List<Track>> GetArtistInfo(string spotifyId);
|
Tuple<Artist, List<Album>> GetArtistInfo(string lidarrId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,18 +9,20 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||||
{
|
{
|
||||||
public AlbumResource()
|
public AlbumResource()
|
||||||
{
|
{
|
||||||
|
Tracks = new List<TrackResource>();
|
||||||
}
|
}
|
||||||
//public string AlbumType { get; set; } // Might need to make this a separate class
|
//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 List<ArtistResource> 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 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 string Id { get; set; } // This is a unique Album ID. Needed for all future API calls
|
||||||
public int Year { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public List<ImageResource> Images { get; set; }
|
public List<ImageResource> Images { get; set; }
|
||||||
public string AlbumName { get; set; } // In case of a takedown, this may be empty
|
public string Title { get; set; } // In case of a takedown, this may be empty
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
public string Label { get; set; }
|
public string Label { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public List<TrackResource> Tracks { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||||
{
|
{
|
||||||
public ArtistResource() {
|
public ArtistResource() {
|
||||||
Albums = new List<AlbumResource>();
|
Albums = new List<AlbumResource>();
|
||||||
Tracks = new List<TrackResource>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
|
@ -19,6 +18,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||||
public List<ImageResource> Images { get; set; }
|
public List<ImageResource> Images { get; set; }
|
||||||
public string ArtistName { get; set; }
|
public string ArtistName { get; set; }
|
||||||
public List<AlbumResource> Albums { get; set; }
|
public List<AlbumResource> Albums { get; set; }
|
||||||
public List<TrackResource> Tracks { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,14 +74,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Tuple<Artist, List<Track>> GetArtistInfo(string spotifyId)
|
public Tuple<Artist, List<Album>> GetArtistInfo(string foreignArtistId)
|
||||||
{
|
{
|
||||||
|
|
||||||
_logger.Debug("Getting Artist with SpotifyId of {0}", spotifyId);
|
_logger.Debug("Getting Artist with SpotifyId of {0}", foreignArtistId);
|
||||||
|
|
||||||
// We need to perform a direct lookup of the artist
|
// We need to perform a direct lookup of the artist
|
||||||
var httpRequest = _requestBuilder.Create()
|
var httpRequest = _requestBuilder.Create()
|
||||||
.SetSegment("route", "artists/" + spotifyId)
|
.SetSegment("route", "artists/" + foreignArtistId)
|
||||||
//.SetSegment("route", "search")
|
//.SetSegment("route", "search")
|
||||||
//.AddQueryParam("type", "artist,album")
|
//.AddQueryParam("type", "artist,album")
|
||||||
//.AddQueryParam("q", spotifyId.ToString())
|
//.AddQueryParam("q", spotifyId.ToString())
|
||||||
|
@ -99,7 +99,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
{
|
{
|
||||||
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
throw new ArtistNotFoundException(spotifyId);
|
throw new ArtistNotFoundException(foreignArtistId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
|
|
||||||
// It is safe to assume an id will only return one Artist back
|
// It is safe to assume an id will only return one Artist back
|
||||||
var albums = httpResponse.Resource.Albums.Select(MapAlbum);
|
var albums = httpResponse.Resource.Albums.Select(MapAlbum);
|
||||||
var tracks = httpResponse.Resource.Tracks.Select(MapTrack);
|
|
||||||
var artist = MapArtist(httpResponse.Resource);
|
var artist = MapArtist(httpResponse.Resource);
|
||||||
|
|
||||||
//artist.Name = httpResponse.Resource.Artists.Items[0].ArtistName;
|
//artist.Name = httpResponse.Resource.Artists.Items[0].ArtistName;
|
||||||
|
@ -120,7 +119,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
//var albumRet = MapAlbums(artist);
|
//var albumRet = MapAlbums(artist);
|
||||||
//artist = albumRet.Item1;
|
//artist = albumRet.Item1;
|
||||||
|
|
||||||
return new Tuple<Artist, List<Track>>(artist, tracks.ToList());
|
return new Tuple<Artist, List<Album>>(artist, albums.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,7 +178,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// List<Track> tracks = new List<Track>();
|
// List<Track> tracks = new List<Track>();
|
||||||
// foreach(var trackResource in httpResponse.Resource.Items)
|
// foreach (var trackResource in httpResponse.Resource.Items)
|
||||||
// {
|
// {
|
||||||
// Track track = new Track();
|
// Track track = new Track();
|
||||||
// track.AlbumId = album.AlbumId;
|
// track.AlbumId = album.AlbumId;
|
||||||
|
@ -269,12 +268,25 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
private static Album MapAlbum(AlbumResource resource)
|
private static Album MapAlbum(AlbumResource resource)
|
||||||
{
|
{
|
||||||
Album album = new Album();
|
Album album = new Album();
|
||||||
|
album.Title = resource.Title;
|
||||||
|
album.ForeignAlbumId = resource.Id;
|
||||||
|
album.ReleaseDate = resource.ReleaseDate;
|
||||||
|
album.CleanTitle = Parser.Parser.CleanArtistTitle(album.Title);
|
||||||
|
album.AlbumType = resource.Type;
|
||||||
|
|
||||||
|
var tracks = resource.Tracks.Select(MapTrack);
|
||||||
|
album.Tracks = tracks.ToList();
|
||||||
|
|
||||||
|
|
||||||
return album;
|
return album;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Track MapTrack(TrackResource resource)
|
private static Track MapTrack(TrackResource resource)
|
||||||
{
|
{
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
|
track.Title = resource.TrackName;
|
||||||
|
track.ForeignTrackId = resource.Id;
|
||||||
|
track.TrackNumber = resource.TrackNumber;
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,11 @@ namespace NzbDrone.Core.Music
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(newArtist.Path))
|
if (string.IsNullOrWhiteSpace(newArtist.Path))
|
||||||
{
|
{
|
||||||
var folderName = newArtist.Name;// TODO: _fileNameBuilder.GetArtistFolder(newArtist);
|
var folderName = _fileNameBuilder.GetArtistFolder(newArtist);
|
||||||
newArtist.Path = Path.Combine(newArtist.RootFolderPath, folderName);
|
newArtist.Path = Path.Combine(newArtist.RootFolderPath, folderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
newArtist.CleanName = newArtist.Name.CleanSeriesTitle();
|
newArtist.CleanName = newArtist.Name.CleanArtistTitle();
|
||||||
//newArtist.SortTitle = ArtistNameNormalizer.Normalize(newArtist.ArtistName, newArtist.ItunesId); // There is no Sort Title
|
//newArtist.SortTitle = ArtistNameNormalizer.Normalize(newArtist.ArtistName, newArtist.ItunesId); // There is no Sort Title
|
||||||
newArtist.Added = DateTime.UtcNow;
|
newArtist.Added = DateTime.UtcNow;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ namespace NzbDrone.Core.Music
|
||||||
|
|
||||||
private Artist AddSkyhookData(Artist newArtist)
|
private Artist AddSkyhookData(Artist newArtist)
|
||||||
{
|
{
|
||||||
Tuple<Artist, List<Track>> tuple;
|
Tuple<Artist, List<Album>> tuple;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace NzbDrone.Core.Music
|
||||||
}
|
}
|
||||||
catch (ArtistNotFoundException)
|
catch (ArtistNotFoundException)
|
||||||
{
|
{
|
||||||
_logger.Error("SpotifyId {1} was not found, it may have been removed from Spotify.", newArtist.ForeignArtistId);
|
_logger.Error("LidarrId {1} was not found, it may have been removed from Lidarr.", newArtist.ForeignArtistId);
|
||||||
|
|
||||||
throw new ValidationException(new List<ValidationFailure>
|
throw new ValidationException(new List<ValidationFailure>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -14,17 +15,27 @@ namespace NzbDrone.Core.Music
|
||||||
Images = new List<MediaCover.MediaCover>();
|
Images = new List<MediaCover.MediaCover>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AlbumId { get; set; }
|
public string ForeignAlbumId { get; set; }
|
||||||
|
public int ArtistId { get; set; }
|
||||||
public string Title { get; set; } // NOTE: This should be CollectionName in API
|
public string Title { get; set; } // NOTE: This should be CollectionName in API
|
||||||
public int Year { get; set; }
|
public string CleanTitle { get; set; }
|
||||||
public int TrackCount { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
|
//public int TrackCount { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
public List<Track> Tracks { get; set; }
|
public List<Track> Tracks { get; set; }
|
||||||
public int DiscCount { get; set; }
|
//public int DiscCount { get; set; }
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
public List<MediaCover.MediaCover> Images { get; set; }
|
public List<MediaCover.MediaCover> Images { get; set; }
|
||||||
public List<Actor> Actors { get; set; } // These are band members. TODO: Refactor
|
//public List<Actor> Actors { get; set; } // These are band members. TODO: Refactor
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
public string ArtworkUrl { get; set; }
|
public String AlbumType { get; set; } //Turn this into a type similar to Series Type in TV
|
||||||
public string Explicitness { get; set; }
|
//public string ArtworkUrl { get; set; }
|
||||||
|
//public string Explicitness { get; set; }
|
||||||
|
public AddSeriesOptions AddOptions { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("[{0}][{1}]", ForeignAlbumId, Title.NullSafe());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/NzbDrone.Core/Music/AlbumRepository.cs
Normal file
46
src/NzbDrone.Core/Music/AlbumRepository.cs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music
|
||||||
|
{
|
||||||
|
public interface IAlbumRepository : IBasicRepository<Album>
|
||||||
|
{
|
||||||
|
bool AlbumPathExists(string path);
|
||||||
|
List<Album> GetAlbums(int artistId);
|
||||||
|
Album FindByName(string cleanTitle);
|
||||||
|
Album FindById(string spotifyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlbumRepository : BasicRepository<Album>, IAlbumRepository
|
||||||
|
{
|
||||||
|
public AlbumRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||||
|
: base(database, eventAggregator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool AlbumPathExists(string path)
|
||||||
|
{
|
||||||
|
return Query.Where(c => c.Path == path).Any();
|
||||||
|
}
|
||||||
|
public List<Album> GetAlbums(int artistId)
|
||||||
|
{
|
||||||
|
return Query.Where(s => s.ArtistId == artistId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album FindById(string foreignAlbumId)
|
||||||
|
{
|
||||||
|
return Query.Where(s => s.ForeignAlbumId == foreignAlbumId).SingleOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album FindByName(string cleanTitle)
|
||||||
|
{
|
||||||
|
cleanTitle = cleanTitle.ToLowerInvariant();
|
||||||
|
|
||||||
|
return Query.Where(s => s.CleanTitle == cleanTitle)
|
||||||
|
.SingleOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
147
src/NzbDrone.Core/Music/AlbumService.cs
Normal file
147
src/NzbDrone.Core/Music/AlbumService.cs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Music.Events;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music
|
||||||
|
{
|
||||||
|
public interface IAlbumService
|
||||||
|
{
|
||||||
|
Album GetAlbum(int albumid);
|
||||||
|
List<Album> GetAlbums(IEnumerable<int> albumIds);
|
||||||
|
List<Album> GetAlbumsByArtist(int artistId);
|
||||||
|
Album AddAlbum(Album newAlbum);
|
||||||
|
Album FindById(string spotifyId);
|
||||||
|
Album FindByTitleInexact(string title);
|
||||||
|
void DeleteAlbum(int albumId, bool deleteFiles);
|
||||||
|
List<Album> GetAllAlbums();
|
||||||
|
Album UpdateAlbum(Album album);
|
||||||
|
List<Album> UpdateAlbums(List<Album> album);
|
||||||
|
void InsertMany(List<Album> albums);
|
||||||
|
void UpdateMany(List<Album> albums);
|
||||||
|
void DeleteMany(List<Album> albums);
|
||||||
|
bool AlbumPathExists(string folder);
|
||||||
|
void RemoveAddOptions(Album album);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlbumService : IAlbumService
|
||||||
|
{
|
||||||
|
private readonly IAlbumRepository _albumRepository;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly ITrackService _trackService;
|
||||||
|
private readonly IBuildFileNames _fileNameBuilder;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public AlbumService(IAlbumRepository albumRepository,
|
||||||
|
IEventAggregator eventAggregator,
|
||||||
|
ITrackService trackService,
|
||||||
|
IBuildFileNames fileNameBuilder,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_albumRepository = albumRepository;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_trackService = trackService;
|
||||||
|
_fileNameBuilder = fileNameBuilder;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album AddAlbum(Album newAlbum)
|
||||||
|
{
|
||||||
|
_albumRepository.Insert(newAlbum);
|
||||||
|
_eventAggregator.PublishEvent(new AlbumAddedEvent(GetAlbum(newAlbum.Id)));
|
||||||
|
|
||||||
|
return newAlbum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AlbumPathExists(string folder)
|
||||||
|
{
|
||||||
|
return _albumRepository.AlbumPathExists(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteAlbum(int albumId, bool deleteFiles)
|
||||||
|
{
|
||||||
|
var album = _albumRepository.Get(albumId);
|
||||||
|
_albumRepository.Delete(albumId);
|
||||||
|
_eventAggregator.PublishEvent(new AlbumDeletedEvent(album, deleteFiles));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album FindById(string spotifyId)
|
||||||
|
{
|
||||||
|
return _albumRepository.FindById(spotifyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Album FindByTitleInexact(string title)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Album> GetAllAlbums()
|
||||||
|
{
|
||||||
|
return _albumRepository.All().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album GetAlbum(int albumId)
|
||||||
|
{
|
||||||
|
return _albumRepository.Get(albumId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Album> GetAlbums(IEnumerable<int> albumIds)
|
||||||
|
{
|
||||||
|
return _albumRepository.Get(albumIds).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Album> GetAlbumsByArtist(int artistId)
|
||||||
|
{
|
||||||
|
return _albumRepository.GetAlbums(artistId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAddOptions(Album album)
|
||||||
|
{
|
||||||
|
_albumRepository.SetFields(album, s => s.AddOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertMany(List<Album> albums)
|
||||||
|
{
|
||||||
|
_albumRepository.InsertMany(albums);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMany(List<Album> albums)
|
||||||
|
{
|
||||||
|
_albumRepository.UpdateMany(albums);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMany(List<Album> albums)
|
||||||
|
{
|
||||||
|
_albumRepository.DeleteMany(albums);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Album UpdateAlbum(Album album)
|
||||||
|
{
|
||||||
|
var storedAlbum = GetAlbum(album.Id); // Is it Id or iTunesId?
|
||||||
|
|
||||||
|
var updatedAlbum = _albumRepository.Update(album);
|
||||||
|
_eventAggregator.PublishEvent(new AlbumEditedEvent(updatedAlbum, storedAlbum));
|
||||||
|
|
||||||
|
return updatedAlbum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Album> UpdateAlbums(List<Album> album)
|
||||||
|
{
|
||||||
|
_logger.Debug("Updating {0} album", album.Count);
|
||||||
|
|
||||||
|
_albumRepository.UpdateMany(album);
|
||||||
|
_logger.Debug("{0} albums updated", album.Count);
|
||||||
|
|
||||||
|
return album;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,11 +110,11 @@ namespace NzbDrone.Core.Music
|
||||||
|
|
||||||
foreach (var album in artist.Albums)
|
foreach (var album in artist.Albums)
|
||||||
{
|
{
|
||||||
var storedAlbum = storedArtist.Albums.SingleOrDefault(s => s.AlbumId == album.AlbumId);
|
var storedAlbum = storedArtist.Albums.SingleOrDefault(s => s.ForeignAlbumId == album.ForeignAlbumId);
|
||||||
|
|
||||||
if (storedAlbum != null && album.Monitored != storedAlbum.Monitored)
|
if (storedAlbum != null && album.Monitored != storedAlbum.Monitored)
|
||||||
{
|
{
|
||||||
_trackService.SetTrackMonitoredByAlbum(artist.ForeignArtistId, album.AlbumId, album.Monitored);
|
_trackService.SetTrackMonitoredByAlbum(artist.ForeignArtistId, album.ForeignAlbumId, album.Monitored);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
src/NzbDrone.Core/Music/Events/AlbumAddedEvent.cs
Normal file
18
src/NzbDrone.Core/Music/Events/AlbumAddedEvent.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music.Events
|
||||||
|
{
|
||||||
|
public class AlbumAddedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Album Album { get; private set; }
|
||||||
|
|
||||||
|
public AlbumAddedEvent(Album album)
|
||||||
|
{
|
||||||
|
Album = album;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/NzbDrone.Core/Music/Events/AlbumDeletedEvent.cs
Normal file
20
src/NzbDrone.Core/Music/Events/AlbumDeletedEvent.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music.Events
|
||||||
|
{
|
||||||
|
public class AlbumDeletedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Album Album { get; private set; }
|
||||||
|
public bool DeleteFiles { get; private set; }
|
||||||
|
|
||||||
|
public AlbumDeletedEvent(Album album, bool deleteFiles)
|
||||||
|
{
|
||||||
|
Album = album;
|
||||||
|
DeleteFiles = deleteFiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/NzbDrone.Core/Music/Events/AlbumEditedEvent.cs
Normal file
20
src/NzbDrone.Core/Music/Events/AlbumEditedEvent.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music.Events
|
||||||
|
{
|
||||||
|
public class AlbumEditedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Album Album { get; private set; }
|
||||||
|
public Album OldAlbum { get; private set; }
|
||||||
|
|
||||||
|
public AlbumEditedEvent(Album album, Album oldAlbum)
|
||||||
|
{
|
||||||
|
Album = album;
|
||||||
|
OldAlbum = oldAlbum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
src/NzbDrone.Core/Music/Events/AlbumInfoRefreshedEvent.cs
Normal file
23
src/NzbDrone.Core/Music/Events/AlbumInfoRefreshedEvent.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music.Events
|
||||||
|
{
|
||||||
|
public class AlbumInfoRefreshedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Artist Artist { get; set; }
|
||||||
|
public ReadOnlyCollection<Album> Added { get; private set; }
|
||||||
|
public ReadOnlyCollection<Album> Updated { get; private set; }
|
||||||
|
|
||||||
|
public AlbumInfoRefreshedEvent(Artist artist, IList<Album> added, IList<Album> updated)
|
||||||
|
{
|
||||||
|
Artist = artist;
|
||||||
|
Added = new ReadOnlyCollection<Album>(added);
|
||||||
|
Updated = new ReadOnlyCollection<Album>(updated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,13 +9,13 @@ namespace NzbDrone.Core.Music.Events
|
||||||
{
|
{
|
||||||
public class TrackInfoRefreshedEvent : IEvent
|
public class TrackInfoRefreshedEvent : IEvent
|
||||||
{
|
{
|
||||||
public Artist Artist { get; set; }
|
public Album Album { get; set; }
|
||||||
public ReadOnlyCollection<Track> Added { get; private set; }
|
public ReadOnlyCollection<Track> Added { get; private set; }
|
||||||
public ReadOnlyCollection<Track> Updated { get; private set; }
|
public ReadOnlyCollection<Track> Updated { get; private set; }
|
||||||
|
|
||||||
public TrackInfoRefreshedEvent(Artist artist, IList<Track> added, IList<Track> updated)
|
public TrackInfoRefreshedEvent(Album album, IList<Track> added, IList<Track> updated)
|
||||||
{
|
{
|
||||||
Artist = artist;
|
Album = album;
|
||||||
Added = new ReadOnlyCollection<Track>(added);
|
Added = new ReadOnlyCollection<Track>(added);
|
||||||
Updated = new ReadOnlyCollection<Track>(updated);
|
Updated = new ReadOnlyCollection<Track>(updated);
|
||||||
}
|
}
|
||||||
|
|
133
src/NzbDrone.Core/Music/RefreshAlbumService.cs
Normal file
133
src/NzbDrone.Core/Music/RefreshAlbumService.cs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Music.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Music
|
||||||
|
{
|
||||||
|
public interface IRefreshAlbumService
|
||||||
|
{
|
||||||
|
void RefreshAlbumInfo(Artist artist, IEnumerable<Album> remoteAlbums);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RefreshAlbumService : IRefreshAlbumService
|
||||||
|
{
|
||||||
|
private readonly IAlbumService _albumService;
|
||||||
|
private readonly IRefreshTrackService _refreshTrackService;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public RefreshAlbumService(IAlbumService albumService, IRefreshTrackService refreshTrackService, IEventAggregator eventAggregator, Logger logger)
|
||||||
|
{
|
||||||
|
_albumService = albumService;
|
||||||
|
_refreshTrackService = refreshTrackService;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshAlbumInfo(Artist artist, IEnumerable<Album> remoteAlbums)
|
||||||
|
{
|
||||||
|
_logger.Info("Starting album info refresh for: {0}", artist);
|
||||||
|
var successCount = 0;
|
||||||
|
var failCount = 0;
|
||||||
|
|
||||||
|
var existingAlbums = _albumService.GetAlbumsByArtist(artist.Id);
|
||||||
|
var albums = artist.Albums;
|
||||||
|
|
||||||
|
var updateList = new List<Album>();
|
||||||
|
var newList = new List<Album>();
|
||||||
|
var dupeFreeRemoteAlbums = remoteAlbums.DistinctBy(m => new { m.ForeignAlbumId, m.ReleaseDate }).ToList();
|
||||||
|
|
||||||
|
foreach (var album in OrderAlbums(artist, dupeFreeRemoteAlbums))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var albumToUpdate = GetAlbumToUpdate(artist, album, existingAlbums);
|
||||||
|
|
||||||
|
if (albumToUpdate != null)
|
||||||
|
{
|
||||||
|
existingAlbums.Remove(albumToUpdate);
|
||||||
|
updateList.Add(albumToUpdate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
albumToUpdate = new Album();
|
||||||
|
albumToUpdate.Monitored = artist.Monitored;
|
||||||
|
newList.Add(albumToUpdate);
|
||||||
|
//var folderName = _fileNameBuilder.GetAlbumFolder(albumToUpdate); //This likely does not belong here, need to create AddAlbumService
|
||||||
|
//albumToUpdate.Path = Path.Combine(newArtist.RootFolderPath, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
albumToUpdate.ForeignAlbumId = album.ForeignAlbumId;
|
||||||
|
albumToUpdate.CleanTitle = album.CleanTitle;
|
||||||
|
//albumToUpdate.TrackNumber = album.TrackNumber;
|
||||||
|
albumToUpdate.Title = album.Title ?? "Unknown";
|
||||||
|
//albumToUpdate.AlbumId = album.AlbumId;
|
||||||
|
//albumToUpdate.Album = album.Album;
|
||||||
|
//albumToUpdate.Explicit = album.Explicit;
|
||||||
|
albumToUpdate.ArtistId = artist.Id;
|
||||||
|
albumToUpdate.Path = artist.Path + album.Title;
|
||||||
|
albumToUpdate.AlbumType = album.AlbumType;
|
||||||
|
//albumToUpdate.Compilation = album.Compilation;
|
||||||
|
|
||||||
|
_refreshTrackService.RefreshTrackInfo(album, album.Tracks);
|
||||||
|
|
||||||
|
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Fatal(e, "An error has occurred while updating track info for artist {0}. {1}", artist, album);
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var allAlbums = new List<Album>();
|
||||||
|
allAlbums.AddRange(newList);
|
||||||
|
allAlbums.AddRange(updateList);
|
||||||
|
|
||||||
|
// TODO: See if anything needs to be done here
|
||||||
|
//AdjustMultiEpisodeAirTime(artist, allTracks);
|
||||||
|
//AdjustDirectToDvdAirDate(artist, allTracks);
|
||||||
|
|
||||||
|
_albumService.DeleteMany(existingAlbums);
|
||||||
|
_albumService.UpdateMany(updateList);
|
||||||
|
_albumService.InsertMany(newList);
|
||||||
|
|
||||||
|
_eventAggregator.PublishEvent(new AlbumInfoRefreshedEvent(artist, newList, updateList));
|
||||||
|
|
||||||
|
if (failCount != 0)
|
||||||
|
{
|
||||||
|
_logger.Info("Finished album refresh for artist: {0}. Successful: {1} - Failed: {2} ",
|
||||||
|
artist.Name, successCount, failCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Info("Finished album refresh for artist: {0}.", artist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GetMonitoredStatus(Album album, IEnumerable<Artist> artists)
|
||||||
|
{
|
||||||
|
var artist = artists.SingleOrDefault(c => c.Id == album.ArtistId);
|
||||||
|
return album == null || album.Monitored;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Album GetAlbumToUpdate(Artist artist, Album album, List<Album> existingAlbums)
|
||||||
|
{
|
||||||
|
return existingAlbums.FirstOrDefault(e => e.ForeignAlbumId == album.ForeignAlbumId && e.ReleaseDate == album.ReleaseDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Album> OrderAlbums(Artist artist, List<Album> albums)
|
||||||
|
{
|
||||||
|
return albums.OrderBy(e => e.ForeignAlbumId).ThenBy(e => e.ReleaseDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Music
|
||||||
{
|
{
|
||||||
private readonly IProvideArtistInfo _artistInfo;
|
private readonly IProvideArtistInfo _artistInfo;
|
||||||
private readonly IArtistService _artistService;
|
private readonly IArtistService _artistService;
|
||||||
private readonly IRefreshTrackService _refreshTrackService;
|
private readonly IRefreshAlbumService _refreshAlbumService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IDiskScanService _diskScanService;
|
||||||
private readonly ICheckIfArtistShouldBeRefreshed _checkIfArtistShouldBeRefreshed;
|
private readonly ICheckIfArtistShouldBeRefreshed _checkIfArtistShouldBeRefreshed;
|
||||||
|
@ -28,7 +28,7 @@ namespace NzbDrone.Core.Music
|
||||||
|
|
||||||
public RefreshArtistService(IProvideArtistInfo artistInfo,
|
public RefreshArtistService(IProvideArtistInfo artistInfo,
|
||||||
IArtistService artistService,
|
IArtistService artistService,
|
||||||
IRefreshTrackService refreshTrackService,
|
IRefreshAlbumService refreshAlbumService,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IDiskScanService diskScanService,
|
IDiskScanService diskScanService,
|
||||||
ICheckIfArtistShouldBeRefreshed checkIfArtistShouldBeRefreshed,
|
ICheckIfArtistShouldBeRefreshed checkIfArtistShouldBeRefreshed,
|
||||||
|
@ -36,7 +36,7 @@ namespace NzbDrone.Core.Music
|
||||||
{
|
{
|
||||||
_artistInfo = artistInfo;
|
_artistInfo = artistInfo;
|
||||||
_artistService = artistService;
|
_artistService = artistService;
|
||||||
_refreshTrackService = refreshTrackService;
|
_refreshAlbumService = refreshAlbumService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_diskScanService = diskScanService;
|
_diskScanService = diskScanService;
|
||||||
_checkIfArtistShouldBeRefreshed = checkIfArtistShouldBeRefreshed;
|
_checkIfArtistShouldBeRefreshed = checkIfArtistShouldBeRefreshed;
|
||||||
|
@ -47,7 +47,7 @@ namespace NzbDrone.Core.Music
|
||||||
{
|
{
|
||||||
_logger.ProgressInfo("Updating Info for {0}", artist.Name);
|
_logger.ProgressInfo("Updating Info for {0}", artist.Name);
|
||||||
|
|
||||||
Tuple<Artist, List<Track>> tuple;
|
Tuple<Artist, List<Album>> tuple;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,8 @@ namespace NzbDrone.Core.Music
|
||||||
artist.Albums = UpdateAlbums(artist, artistInfo);
|
artist.Albums = UpdateAlbums(artist, artistInfo);
|
||||||
|
|
||||||
_artistService.UpdateArtist(artist);
|
_artistService.UpdateArtist(artist);
|
||||||
_refreshTrackService.RefreshTrackInfo(artist, tuple.Item2);
|
_refreshAlbumService.RefreshAlbumInfo(artist, tuple.Item2);
|
||||||
|
//_refreshTrackService.RefreshTrackInfo(artist, tuple.Item2);
|
||||||
|
|
||||||
_logger.Debug("Finished artist refresh for {0}", artist.Name);
|
_logger.Debug("Finished artist refresh for {0}", artist.Name);
|
||||||
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
|
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
|
||||||
|
@ -97,11 +98,11 @@ namespace NzbDrone.Core.Music
|
||||||
|
|
||||||
private List<Album> UpdateAlbums(Artist artist, Artist artistInfo)
|
private List<Album> UpdateAlbums(Artist artist, Artist artistInfo)
|
||||||
{
|
{
|
||||||
var albums = artistInfo.Albums.DistinctBy(s => s.AlbumId).ToList();
|
var albums = artistInfo.Albums.DistinctBy(s => s.ForeignAlbumId).ToList();
|
||||||
|
|
||||||
foreach (var album in albums)
|
foreach (var album in albums)
|
||||||
{
|
{
|
||||||
var existingAlbum = artist.Albums.FirstOrDefault(s => s.AlbumId == album.AlbumId);
|
var existingAlbum = artist.Albums.FirstOrDefault(s => s.ForeignAlbumId == album.ForeignAlbumId);
|
||||||
|
|
||||||
//Todo: Should this should use the previous season's monitored state?
|
//Todo: Should this should use the previous season's monitored state?
|
||||||
if (existingAlbum == null)
|
if (existingAlbum == null)
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace NzbDrone.Core.Music
|
||||||
{
|
{
|
||||||
public interface IRefreshTrackService
|
public interface IRefreshTrackService
|
||||||
{
|
{
|
||||||
void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks);
|
void RefreshTrackInfo(Album album, IEnumerable<Track> remoteTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RefreshTrackService : IRefreshTrackService
|
public class RefreshTrackService : IRefreshTrackService
|
||||||
|
@ -27,24 +27,24 @@ namespace NzbDrone.Core.Music
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks)
|
public void RefreshTrackInfo(Album album, IEnumerable<Track> remoteTracks)
|
||||||
{
|
{
|
||||||
_logger.Info("Starting track info refresh for: {0}", artist);
|
_logger.Info("Starting track info refresh for: {0}", album);
|
||||||
var successCount = 0;
|
var successCount = 0;
|
||||||
var failCount = 0;
|
var failCount = 0;
|
||||||
|
|
||||||
var existingTracks = _trackService.GetTracksByArtist(artist.Id);
|
var existingTracks = _trackService.GetTracksByAlbum(album.ArtistId, album.Id);
|
||||||
var albums = artist.Albums;
|
//var albums = artist.Albums;
|
||||||
|
|
||||||
var updateList = new List<Track>();
|
var updateList = new List<Track>();
|
||||||
var newList = new List<Track>();
|
var newList = new List<Track>();
|
||||||
var dupeFreeRemoteTracks = remoteTracks.DistinctBy(m => new { m.AlbumId, m.TrackNumber }).ToList();
|
var dupeFreeRemoteTracks = remoteTracks.DistinctBy(m => new { m.AlbumId, m.TrackNumber }).ToList();
|
||||||
|
|
||||||
foreach (var track in OrderTracks(artist, dupeFreeRemoteTracks))
|
foreach (var track in OrderTracks(album, dupeFreeRemoteTracks))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var trackToUpdate = GetTrackToUpdate(artist, track, existingTracks);
|
var trackToUpdate = GetTrackToUpdate(album, track, existingTracks);
|
||||||
|
|
||||||
if (trackToUpdate != null)
|
if (trackToUpdate != null)
|
||||||
{
|
{
|
||||||
|
@ -54,17 +54,17 @@ namespace NzbDrone.Core.Music
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trackToUpdate = new Track();
|
trackToUpdate = new Track();
|
||||||
trackToUpdate.Monitored = GetMonitoredStatus(track, albums);
|
trackToUpdate.Monitored = album.Monitored;
|
||||||
newList.Add(trackToUpdate);
|
newList.Add(trackToUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
trackToUpdate.ForeignTrackId = track.ForeignTrackId;
|
trackToUpdate.ForeignTrackId = track.ForeignTrackId;
|
||||||
trackToUpdate.TrackNumber = track.TrackNumber;
|
trackToUpdate.TrackNumber = track.TrackNumber;
|
||||||
trackToUpdate.Title = track.Title ?? "Unknown";
|
trackToUpdate.Title = track.Title ?? "Unknown";
|
||||||
trackToUpdate.AlbumId = track.AlbumId;
|
trackToUpdate.AlbumId = album.Id;
|
||||||
trackToUpdate.Album = track.Album;
|
trackToUpdate.Album = track.Album;
|
||||||
trackToUpdate.Explicit = track.Explicit;
|
trackToUpdate.Explicit = track.Explicit;
|
||||||
trackToUpdate.ArtistId = artist.Id;
|
trackToUpdate.ArtistId = album.ArtistId;
|
||||||
trackToUpdate.Compilation = track.Compilation;
|
trackToUpdate.Compilation = track.Compilation;
|
||||||
|
|
||||||
// TODO: Implement rest of [RefreshTrackService] fields
|
// TODO: Implement rest of [RefreshTrackService] fields
|
||||||
|
@ -75,7 +75,7 @@ namespace NzbDrone.Core.Music
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Fatal(e, "An error has occurred while updating track info for artist {0}. {1}", artist, track);
|
_logger.Fatal(e, "An error has occurred while updating track info for album {0}. {1}", album, track);
|
||||||
failCount++;
|
failCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,16 +92,16 @@ namespace NzbDrone.Core.Music
|
||||||
_trackService.UpdateMany(updateList);
|
_trackService.UpdateMany(updateList);
|
||||||
_trackService.InsertMany(newList);
|
_trackService.InsertMany(newList);
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new TrackInfoRefreshedEvent(artist, newList, updateList));
|
_eventAggregator.PublishEvent(new TrackInfoRefreshedEvent(album, newList, updateList));
|
||||||
|
|
||||||
if (failCount != 0)
|
if (failCount != 0)
|
||||||
{
|
{
|
||||||
_logger.Info("Finished track refresh for artist: {0}. Successful: {1} - Failed: {2} ",
|
_logger.Info("Finished track refresh for album: {0}. Successful: {1} - Failed: {2} ",
|
||||||
artist.Name, successCount, failCount);
|
album.Title, successCount, failCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Info("Finished track refresh for artist: {0}.", artist);
|
_logger.Info("Finished track refresh for album: {0}.", album);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +117,12 @@ namespace NzbDrone.Core.Music
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Track GetTrackToUpdate(Artist artist, Track track, List<Track> existingTracks)
|
private Track GetTrackToUpdate(Album album, Track track, List<Track> existingTracks)
|
||||||
{
|
{
|
||||||
return existingTracks.FirstOrDefault(e => e.AlbumId == track.AlbumId && e.TrackNumber == track.TrackNumber);
|
return existingTracks.FirstOrDefault(e => e.AlbumId == track.AlbumId && e.TrackNumber == track.TrackNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Track> OrderTracks(Artist artist, List<Track> tracks)
|
private IEnumerable<Track> OrderTracks(Album album, List<Track> tracks)
|
||||||
{
|
{
|
||||||
return tracks.OrderBy(e => e.AlbumId).ThenBy(e => e.TrackNumber);
|
return tracks.OrderBy(e => e.AlbumId).ThenBy(e => e.TrackNumber);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace NzbDrone.Core.Music
|
||||||
Track FindTrack(int artistId, int albumId, int trackNumber);
|
Track FindTrack(int artistId, int albumId, int trackNumber);
|
||||||
Track FindTrackByTitle(int artistId, int albumId, string releaseTitle);
|
Track FindTrackByTitle(int artistId, int albumId, string releaseTitle);
|
||||||
List<Track> GetTracksByArtist(int artistId);
|
List<Track> GetTracksByArtist(int artistId);
|
||||||
//List<Track> GetTracksByAlbum(string artistId, string albumId);
|
List<Track> GetTracksByAlbum(int artistId, int albumId);
|
||||||
//List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle);
|
//List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle);
|
||||||
List<Track> TracksWithFiles(int artistId);
|
List<Track> TracksWithFiles(int artistId);
|
||||||
//PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
//PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
||||||
|
|
|
@ -856,17 +856,24 @@
|
||||||
<Compile Include="Music\Artist.cs" />
|
<Compile Include="Music\Artist.cs" />
|
||||||
<Compile Include="Music\ArtistAddedHandler.cs" />
|
<Compile Include="Music\ArtistAddedHandler.cs" />
|
||||||
<Compile Include="Music\ArtistNameNormalizer.cs" />
|
<Compile Include="Music\ArtistNameNormalizer.cs" />
|
||||||
|
<Compile Include="Music\AlbumService.cs" />
|
||||||
|
<Compile Include="Music\AlbumRepository.cs" />
|
||||||
<Compile Include="Music\ArtistSlugValidator.cs" />
|
<Compile Include="Music\ArtistSlugValidator.cs" />
|
||||||
<Compile Include="Music\ArtistRepository.cs" />
|
<Compile Include="Music\ArtistRepository.cs" />
|
||||||
<Compile Include="Music\ArtistService.cs" />
|
<Compile Include="Music\ArtistService.cs" />
|
||||||
<Compile Include="Music\Commands\RefreshArtistCommand.cs" />
|
<Compile Include="Music\Commands\RefreshArtistCommand.cs" />
|
||||||
|
<Compile Include="Music\Events\AlbumAddedEvent.cs" />
|
||||||
<Compile Include="Music\Events\ArtistAddedEvent.cs" />
|
<Compile Include="Music\Events\ArtistAddedEvent.cs" />
|
||||||
|
<Compile Include="Music\Events\AlbumDeletedEvent.cs" />
|
||||||
<Compile Include="Music\Events\ArtistDeletedEvent.cs" />
|
<Compile Include="Music\Events\ArtistDeletedEvent.cs" />
|
||||||
|
<Compile Include="Music\Events\AlbumEditedEvent.cs" />
|
||||||
<Compile Include="Music\Events\ArtistEditedEvent.cs" />
|
<Compile Include="Music\Events\ArtistEditedEvent.cs" />
|
||||||
<Compile Include="Music\Events\ArtistRefreshStartingEvent.cs" />
|
<Compile Include="Music\Events\ArtistRefreshStartingEvent.cs" />
|
||||||
<Compile Include="Music\Events\ArtistUpdatedEvent.cs" />
|
<Compile Include="Music\Events\ArtistUpdatedEvent.cs" />
|
||||||
|
<Compile Include="Music\Events\AlbumInfoRefreshedEvent.cs" />
|
||||||
<Compile Include="Music\Events\TrackInfoRefreshedEvent.cs" />
|
<Compile Include="Music\Events\TrackInfoRefreshedEvent.cs" />
|
||||||
<Compile Include="Music\RefreshArtistService.cs" />
|
<Compile Include="Music\RefreshArtistService.cs" />
|
||||||
|
<Compile Include="Music\RefreshAlbumService.cs" />
|
||||||
<Compile Include="Music\RefreshTrackService.cs" />
|
<Compile Include="Music\RefreshTrackService.cs" />
|
||||||
<Compile Include="Music\ShouldRefreshArtist.cs" />
|
<Compile Include="Music\ShouldRefreshArtist.cs" />
|
||||||
<Compile Include="Music\Track.cs" />
|
<Compile Include="Music\Track.cs" />
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace NzbDrone.Core.Organizer
|
||||||
string BuildSeasonPath(Series series, int seasonNumber);
|
string BuildSeasonPath(Series series, int seasonNumber);
|
||||||
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
||||||
string GetSeriesFolder(Series series, NamingConfig namingConfig = null);
|
string GetSeriesFolder(Series series, NamingConfig namingConfig = null);
|
||||||
|
string GetArtistFolder(Artist artist, NamingConfig namingConfig = null);
|
||||||
|
string GetAlbumFolder(Album album, NamingConfig namingConfig = null);
|
||||||
string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null);
|
string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null);
|
||||||
|
|
||||||
// TODO: Implement Music functions
|
// TODO: Implement Music functions
|
||||||
|
@ -232,6 +234,20 @@ namespace NzbDrone.Core.Organizer
|
||||||
return CleanFolderName(ReplaceTokens(namingConfig.SeriesFolderFormat, tokenHandlers, namingConfig));
|
return CleanFolderName(ReplaceTokens(namingConfig.SeriesFolderFormat, tokenHandlers, namingConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetArtistFolder(Artist artist, NamingConfig namingConfig = null)
|
||||||
|
{
|
||||||
|
if (namingConfig == null)
|
||||||
|
{
|
||||||
|
namingConfig = _namingConfigService.GetConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||||
|
|
||||||
|
AddArtistTokens(tokenHandlers, artist);
|
||||||
|
|
||||||
|
return CleanFolderName(ReplaceTokens(namingConfig.ArtistFolderFormat, tokenHandlers, namingConfig));
|
||||||
|
}
|
||||||
|
|
||||||
public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null)
|
public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null)
|
||||||
{
|
{
|
||||||
if (namingConfig == null)
|
if (namingConfig == null)
|
||||||
|
@ -247,6 +263,20 @@ namespace NzbDrone.Core.Organizer
|
||||||
return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig));
|
return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetAlbumFolder(Album album, NamingConfig namingConfig = null)
|
||||||
|
{
|
||||||
|
if (namingConfig == null)
|
||||||
|
{
|
||||||
|
namingConfig = _namingConfigService.GetConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||||
|
|
||||||
|
AddAlbumTokens(tokenHandlers, album);
|
||||||
|
|
||||||
|
return CleanFolderName(ReplaceTokens(namingConfig.AlbumFolderFormat, tokenHandlers, namingConfig));
|
||||||
|
}
|
||||||
|
|
||||||
public static string CleanTitle(string title)
|
public static string CleanTitle(string title)
|
||||||
{
|
{
|
||||||
title = title.Replace("&", "and");
|
title = title.Replace("&", "and");
|
||||||
|
@ -285,7 +315,14 @@ namespace NzbDrone.Core.Organizer
|
||||||
private void AddArtistTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Artist artist)
|
private void AddArtistTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Artist artist)
|
||||||
{
|
{
|
||||||
tokenHandlers["{Artist Name}"] = m => artist.Name;
|
tokenHandlers["{Artist Name}"] = m => artist.Name;
|
||||||
tokenHandlers["{Artist CleanTitle}"] = m => CleanTitle(artist.Name);
|
tokenHandlers["{Artist CleanName}"] = m => CleanTitle(artist.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddAlbumTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Album album)
|
||||||
|
{
|
||||||
|
tokenHandlers["{Album Title}"] = m => album.Title;
|
||||||
|
tokenHandlers["{Album CleanTitle}"] = m => CleanTitle(album.Title);
|
||||||
|
tokenHandlers["{Album Year}"] = m => album.ReleaseDate.Year.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Episode> episodes, NamingConfig namingConfig)
|
private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Episode> episodes, NamingConfig namingConfig)
|
||||||
|
|
|
@ -223,12 +223,12 @@ var view = Marionette.ItemView.extend({
|
||||||
self.close();
|
self.close();
|
||||||
|
|
||||||
Messenger.show({
|
Messenger.show({
|
||||||
message : 'Added: ' + self.model.get('artistName'),
|
message : 'Added: ' + self.model.get('name'),
|
||||||
actions : {
|
actions : {
|
||||||
goToArtist : {
|
goToArtist : {
|
||||||
label : 'Go to Artist',
|
label : 'Go to Artist',
|
||||||
action : function() {
|
action : function() {
|
||||||
Backbone.history.navigate('/artist/' + self.model.get('artistSlug'), { trigger : true });
|
Backbone.history.navigate('/artist/' + self.model.get('nameSlug'), { trigger : true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="row new-artist-overview x-overview">
|
<div class="row new-artist-overview x-overview">
|
||||||
<div class="col-md-12 overview-internal">
|
<div class="col-md-12 overview-internal">
|
||||||
{{overview}}
|
{{overview}}
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{#unless existing}}
|
{{#unless existing}}
|
||||||
{{#unless path}}
|
{{#unless path}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue