mirror of
https://github.com/fergalmoran/Readarr.git
synced 2026-01-05 16:25:05 +00:00
New: Manually Edit/Override Album Release (#181)
* New: Manually Edit/Override Album Release * !fixup for comments, loading all albums instead of only artist albums * fixup! UI Cleanup lint issues * fixup! Remove AddAlbum service for now, fix refresh override selected release * fixup! Last one... to fix updating albums with custom release set Closes #109 Closes #129 Closes #128
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.SignalR;
|
||||
@@ -21,7 +22,7 @@ namespace Lidarr.Api.V1.Albums
|
||||
: base(albumService, artistStatisticsService, artistService, upgradableSpecification, signalRBroadcaster)
|
||||
{
|
||||
GetResourceAll = GetAlbums;
|
||||
Put[@"/(?<id>[\d]{1,10})"] = x => SetAlbumMonitored(x.Id);
|
||||
UpdateResource = UpdateAlbum;
|
||||
Put["/monitor"] = x => SetAlbumsMonitored();
|
||||
}
|
||||
|
||||
@@ -29,8 +30,9 @@ namespace Lidarr.Api.V1.Albums
|
||||
{
|
||||
var artistIdQuery = Request.Query.ArtistId;
|
||||
var albumIdsQuery = Request.Query.AlbumIds;
|
||||
var foreignIdQuery = Request.Query.ForeignAlbumId;
|
||||
|
||||
if (!Request.Query.ArtistId.HasValue && !albumIdsQuery.HasValue)
|
||||
if (!Request.Query.ArtistId.HasValue && !albumIdsQuery.HasValue && !foreignIdQuery.HasValue)
|
||||
{
|
||||
return MapToResource(_albumService.GetAllAlbums(), false);
|
||||
}
|
||||
@@ -42,6 +44,13 @@ namespace Lidarr.Api.V1.Albums
|
||||
return MapToResource(_albumService.GetAlbumsByArtist(artistId), false);
|
||||
}
|
||||
|
||||
if (foreignIdQuery.HasValue)
|
||||
{
|
||||
int artistId = _albumService.FindById(foreignIdQuery.Value).ArtistId;
|
||||
|
||||
return MapToResource(_albumService.GetAlbumsByArtist(artistId), false);
|
||||
}
|
||||
|
||||
string albumIdsValue = albumIdsQuery.Value.ToString();
|
||||
|
||||
var albumIds = albumIdsValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
@@ -51,12 +60,15 @@ namespace Lidarr.Api.V1.Albums
|
||||
return MapToResource(_albumService.GetAlbums(albumIds), false);
|
||||
}
|
||||
|
||||
private Response SetAlbumMonitored(int id)
|
||||
private void UpdateAlbum(AlbumResource albumResource)
|
||||
{
|
||||
var resource = Request.Body.FromJson<AlbumResource>();
|
||||
_albumService.SetAlbumMonitored(id, resource.Monitored);
|
||||
var album = _albumService.GetAlbum(albumResource.Id);
|
||||
|
||||
return MapToResource(_albumService.GetAlbum(id), false).AsResponse(HttpStatusCode.Accepted);
|
||||
var model = albumResource.ToModel(album);
|
||||
|
||||
_albumService.UpdateAlbum(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, albumResource);
|
||||
}
|
||||
|
||||
private Response SetAlbumsMonitored()
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using Lidarr.Api.V1.Artist;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
@@ -9,10 +11,16 @@ using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.ArtistStats;
|
||||
using NzbDrone.SignalR;
|
||||
using Lidarr.Http;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
|
||||
namespace Lidarr.Api.V1.Albums
|
||||
{
|
||||
public abstract class AlbumModuleWithSignalR : LidarrRestModuleWithSignalR<AlbumResource, Album>
|
||||
public abstract class AlbumModuleWithSignalR : LidarrRestModuleWithSignalR<AlbumResource, Album>,
|
||||
IHandle<AlbumGrabbedEvent>,
|
||||
IHandle<AlbumEditedEvent>,
|
||||
IHandle<TrackImportedEvent>
|
||||
{
|
||||
protected readonly IAlbumService _albumService;
|
||||
protected readonly IArtistStatisticsService _artistStatisticsService;
|
||||
@@ -130,18 +138,26 @@ namespace Lidarr.Api.V1.Albums
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Implement Track or Album Grabbed/Dowloaded Events
|
||||
public void Handle(AlbumGrabbedEvent message)
|
||||
{
|
||||
foreach (var album in message.Album.Albums)
|
||||
{
|
||||
var resource = album.ToResource();
|
||||
resource.Grabbed = true;
|
||||
|
||||
//public void Handle(TrackGrabbedEvent message)
|
||||
//{
|
||||
// foreach (var track in message.Track.Tracks)
|
||||
// {
|
||||
// var resource = track.ToResource();
|
||||
// resource.Grabbed = true;
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(AlbumEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Album.Id);
|
||||
}
|
||||
|
||||
// BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
// }
|
||||
//}
|
||||
public void Handle(TrackImportedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.ImportedTrack.AlbumId);
|
||||
}
|
||||
|
||||
//public void Handle(TrackDownloadedEvent message)
|
||||
//{
|
||||
|
||||
72
src/Lidarr.Api.V1/Albums/AlbumReleaseResource.cs
Normal file
72
src/Lidarr.Api.V1/Albums/AlbumReleaseResource.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Music;
|
||||
|
||||
namespace Lidarr.Api.V1.Albums
|
||||
{
|
||||
public class AlbumReleaseResource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Country { get; set; }
|
||||
public List<string> Label { get; set; }
|
||||
public string Format { get; set; }
|
||||
}
|
||||
|
||||
public static class AlbumReleaseResourceMapper
|
||||
{
|
||||
public static AlbumReleaseResource ToResource(this AlbumRelease model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AlbumReleaseResource
|
||||
{
|
||||
Id = model.Id,
|
||||
ReleaseDate = model.ReleaseDate,
|
||||
TrackCount = model.TrackCount,
|
||||
MediaCount = model.MediaCount,
|
||||
Disambiguation = model.Disambiguation,
|
||||
Country = model.Country,
|
||||
Label = model.Label,
|
||||
Format = model.Format
|
||||
};
|
||||
}
|
||||
|
||||
public static AlbumRelease ToModel(this AlbumReleaseResource resource)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AlbumRelease
|
||||
{
|
||||
Id = resource.Id,
|
||||
ReleaseDate = resource.ReleaseDate,
|
||||
TrackCount = resource.TrackCount,
|
||||
MediaCount = resource.MediaCount,
|
||||
Disambiguation = resource.Disambiguation,
|
||||
Country = resource.Country,
|
||||
Label = resource.Label,
|
||||
Format = resource.Format
|
||||
};
|
||||
}
|
||||
|
||||
public static List<AlbumReleaseResource> ToResource(this IEnumerable<AlbumRelease> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<AlbumRelease> ToModel(this IEnumerable<AlbumReleaseResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace Lidarr.Api.V1.Albums
|
||||
public int ProfileId { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public string AlbumType { get; set; }
|
||||
public List<string> SecondaryTypes { get; set; }
|
||||
public int MediumCount
|
||||
{
|
||||
get
|
||||
@@ -33,6 +34,8 @@ namespace Lidarr.Api.V1.Albums
|
||||
}
|
||||
public Ratings Ratings { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public AlbumRelease CurrentRelease { get; set; }
|
||||
public List<AlbumReleaseResource> Releases { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
@@ -65,15 +68,45 @@ namespace Lidarr.Api.V1.Albums
|
||||
Ratings = model.Ratings,
|
||||
Duration = model.Duration,
|
||||
AlbumType = model.AlbumType,
|
||||
SecondaryTypes = model.SecondaryTypes.Select(s => s.Name).ToList(),
|
||||
Media = model.Media.ToResource(),
|
||||
CurrentRelease = model.CurrentRelease,
|
||||
Releases = model.Releases.ToResource(),
|
||||
};
|
||||
}
|
||||
|
||||
public static Album ToModel(this AlbumResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Album
|
||||
{
|
||||
Id = resource.Id,
|
||||
ForeignAlbumId = resource.ForeignAlbumId,
|
||||
Title = resource.Title,
|
||||
Images = resource.Images,
|
||||
Monitored = resource.Monitored,
|
||||
CurrentRelease = resource.CurrentRelease
|
||||
};
|
||||
}
|
||||
|
||||
public static Album ToModel(this AlbumResource resource, Album album)
|
||||
{
|
||||
var updatedAlbum = resource.ToModel();
|
||||
|
||||
album.ApplyChanges(updatedAlbum);
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
public static List<AlbumResource> ToResource(this IEnumerable<Album> models)
|
||||
{
|
||||
if (models == null) return null;
|
||||
return models?.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
return models.Select(ToResource).ToList();
|
||||
public static List<Album> ToModel(this IEnumerable<AlbumResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Lidarr.Api.V1.Albums
|
||||
public string MediumFormat { get; set; }
|
||||
}
|
||||
|
||||
public static class SeasonResourceMapper
|
||||
public static class MediumResourceMapper
|
||||
{
|
||||
public static MediumResource ToResource(this Medium model)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace Lidarr.Api.V1.Artist
|
||||
|
||||
{
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IAddArtistService _addArtistService;
|
||||
private readonly IArtistStatisticsService _artistStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
@@ -41,6 +42,7 @@ namespace Lidarr.Api.V1.Artist
|
||||
|
||||
public ArtistModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IArtistService artistService,
|
||||
IAlbumService albumService,
|
||||
IAddArtistService addArtistService,
|
||||
IArtistStatisticsService artistStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
@@ -57,6 +59,7 @@ namespace Lidarr.Api.V1.Artist
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_artistService = artistService;
|
||||
_albumService = albumService;
|
||||
_addArtistService = addArtistService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
|
||||
@@ -105,6 +108,7 @@ namespace Lidarr.Api.V1.Artist
|
||||
var resource = artist.ToResource();
|
||||
MapCoversToLocal(resource);
|
||||
FetchAndLinkArtistStatistics(resource);
|
||||
LinkNextPreviousAlbums(resource);
|
||||
//PopulateAlternateTitles(resource);
|
||||
|
||||
return resource;
|
||||
@@ -116,7 +120,7 @@ namespace Lidarr.Api.V1.Artist
|
||||
var artistsResources = _artistService.GetAllArtists().ToResource();
|
||||
|
||||
MapCoversToLocal(artistsResources.ToArray());
|
||||
//MapAlbums(artistsResources.ToArray());
|
||||
LinkNextPreviousAlbums(artistsResources.ToArray());
|
||||
LinkArtistStatistics(artistsResources, artistStats);
|
||||
//PopulateAlternateTitles(seriesResources);
|
||||
|
||||
@@ -171,6 +175,16 @@ namespace Lidarr.Api.V1.Artist
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkNextPreviousAlbums(params ArtistResource[] artists)
|
||||
{
|
||||
foreach (var artistResource in artists)
|
||||
{
|
||||
var artistAlbums = _albumService.GetAlbumsByArtist(artistResource.Id).OrderBy(s=>s.ReleaseDate);
|
||||
artistResource.NextAlbum = artistAlbums.Where(s => s.ReleaseDate >= DateTime.UtcNow && s.Monitored).FirstOrDefault();
|
||||
artistResource.LastAlbum = artistAlbums.Where(s => s.ReleaseDate <= DateTime.UtcNow && s.Monitored).LastOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAndLinkArtistStatistics(ArtistResource resource)
|
||||
{
|
||||
LinkArtistStatistics(resource, _artistStatisticsService.ArtistStatistics(resource.Id));
|
||||
@@ -195,13 +209,6 @@ namespace Lidarr.Api.V1.Artist
|
||||
resource.SizeOnDisk = artistStatistics.SizeOnDisk;
|
||||
resource.AlbumCount = artistStatistics.AlbumCount;
|
||||
|
||||
if (artistStatistics.AlbumStatistics != null)
|
||||
{
|
||||
foreach (var album in resource.Albums)
|
||||
{
|
||||
album.Statistics = artistStatistics.AlbumStatistics.SingleOrDefault(s => s.AlbumId == album.Id).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private void PopulateAlternateTitles(List<ArtistResource> resources)
|
||||
|
||||
@@ -36,13 +36,13 @@ namespace Lidarr.Api.V1.Artist
|
||||
public int? TrackCount { get; set; }
|
||||
public int? TrackFileCount { get; set; }
|
||||
public long? SizeOnDisk { get; set; }
|
||||
//public SeriesStatusType Status { get; set; }
|
||||
public Album NextAlbum { get; set; }
|
||||
public Album LastAlbum { get; set; }
|
||||
|
||||
public List<MediaCover> Images { get; set; }
|
||||
public List<Member> Members { get; set; }
|
||||
|
||||
public string RemotePoster { get; set; }
|
||||
public List<AlbumResource> Albums { get; set; }
|
||||
|
||||
|
||||
//View & Edit
|
||||
@@ -89,8 +89,6 @@ namespace Lidarr.Api.V1.Artist
|
||||
|
||||
Images = model.Images,
|
||||
|
||||
Albums = model.Albums.ToResource(),
|
||||
|
||||
Path = model.Path,
|
||||
QualityProfileId = model.ProfileId,
|
||||
LanguageProfileId = model.LanguageProfileId,
|
||||
@@ -128,8 +126,6 @@ namespace Lidarr.Api.V1.Artist
|
||||
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
//NextAiring
|
||||
//PreviousAiring
|
||||
|
||||
Images = resource.Images,
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
</Compile>
|
||||
<Compile Include="Albums\AlbumModule.cs" />
|
||||
<Compile Include="Albums\AlbumModuleWithSignalR.cs" />
|
||||
<Compile Include="Albums\AlbumReleaseResource.cs" />
|
||||
<Compile Include="Albums\AlbumResource.cs" />
|
||||
<Compile Include="Albums\AlbumsMonitoredResource.cs" />
|
||||
<Compile Include="Albums\AlbumStatisticsResource.cs" />
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Lidarr.Api.V1.TrackFiles
|
||||
|
||||
public static class MediaInfoResourceMapper
|
||||
{
|
||||
public static MediaInfoResource ToResource(this MediaInfoModel model, string sceneName)
|
||||
public static MediaInfoResource ToResource(this MediaInfoModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
|
||||
@@ -80,8 +80,9 @@ namespace Lidarr.Api.V1.TrackFiles
|
||||
{
|
||||
int albumId = Convert.ToInt32(albumIdQuery.Value);
|
||||
var album = _albumService.GetAlbum(albumId);
|
||||
var albumArtist = _artistService.GetArtist(album.ArtistId);
|
||||
|
||||
return _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id).ConvertAll(f => f.ToResource(album.Artist, _upgradableSpecification));
|
||||
return _mediaFileService.GetFilesByAlbum(album.Id).ConvertAll(f => f.ToResource(albumArtist, _upgradableSpecification));
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Lidarr.Api.V1.TrackFiles
|
||||
// SceneName = model.SceneName,
|
||||
Language = model.Language,
|
||||
Quality = model.Quality,
|
||||
MediaInfo = model.MediaInfo.ToResource(model.SceneName)
|
||||
MediaInfo = model.MediaInfo.ToResource()
|
||||
//QualityCutoffNotMet
|
||||
};
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Lidarr.Api.V1.TrackFiles
|
||||
//SceneName = model.SceneName,
|
||||
Language = model.Language,
|
||||
Quality = model.Quality,
|
||||
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
|
||||
MediaInfo = model.MediaInfo.ToResource(),
|
||||
|
||||
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(artist.Profile.Value, model.Quality),
|
||||
LanguageCutoffNotMet = upgradableSpecification.LanguageCutoffNotMet(artist.LanguageProfile.Value, model.Language)
|
||||
|
||||
@@ -2,20 +2,20 @@ using System.Collections.Generic;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using NzbDrone.SignalR;
|
||||
using Lidarr.Api.V1.TrackFiles;
|
||||
using Lidarr.Api.V1.Artist;
|
||||
using Lidarr.Http;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
|
||||
namespace Lidarr.Api.V1.Tracks
|
||||
{
|
||||
public abstract class TrackModuleWithSignalR : LidarrRestModuleWithSignalR<TrackResource, Track>
|
||||
//IHandle<EpisodeGrabbedEvent>,
|
||||
//IHandle<EpisodeImportedEvent>
|
||||
public abstract class TrackModuleWithSignalR : LidarrRestModuleWithSignalR<TrackResource, Track>,
|
||||
IHandle<TrackInfoRefreshedEvent>,
|
||||
IHandle<TrackImportedEvent>
|
||||
{
|
||||
protected readonly ITrackService _trackService;
|
||||
protected readonly IArtistService _artistService;
|
||||
@@ -31,24 +31,24 @@ namespace Lidarr.Api.V1.Tracks
|
||||
_artistService = artistService;
|
||||
_upgradableSpecification = upgradableSpecification;
|
||||
|
||||
GetResourceById = GetEpisode;
|
||||
GetResourceById = GetTrack;
|
||||
}
|
||||
|
||||
protected TrackModuleWithSignalR(ITrackService episodeService,
|
||||
IArtistService seriesService,
|
||||
protected TrackModuleWithSignalR(ITrackService trackService,
|
||||
IArtistService artistService,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_trackService = episodeService;
|
||||
_artistService = seriesService;
|
||||
_trackService = trackService;
|
||||
_artistService = artistService;
|
||||
_upgradableSpecification = upgradableSpecification;
|
||||
|
||||
GetResourceById = GetEpisode;
|
||||
GetResourceById = GetTrack;
|
||||
}
|
||||
|
||||
protected TrackResource GetEpisode(int id)
|
||||
protected TrackResource GetTrack(int id)
|
||||
{
|
||||
var episode = _trackService.GetTrack(id);
|
||||
var resource = MapToResource(episode, true, true);
|
||||
@@ -76,28 +76,28 @@ namespace Lidarr.Api.V1.Tracks
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected List<TrackResource> MapToResource(List<Track> episodes, bool includeSeries, bool includeEpisodeFile)
|
||||
protected List<TrackResource> MapToResource(List<Track> tracks, bool includeArtist, bool includeTrackFile)
|
||||
{
|
||||
var result = episodes.ToResource();
|
||||
var result = tracks.ToResource();
|
||||
|
||||
if (includeSeries || includeEpisodeFile)
|
||||
if (includeArtist || includeTrackFile)
|
||||
{
|
||||
var seriesDict = new Dictionary<int, NzbDrone.Core.Music.Artist>();
|
||||
for (var i = 0; i < episodes.Count; i++)
|
||||
var artistDict = new Dictionary<int, NzbDrone.Core.Music.Artist>();
|
||||
for (var i = 0; i < tracks.Count; i++)
|
||||
{
|
||||
var episode = episodes[i];
|
||||
var track = tracks[i];
|
||||
var resource = result[i];
|
||||
|
||||
var series = episode.Artist ?? seriesDict.GetValueOrDefault(episodes[i].ArtistId) ?? _artistService.GetArtist(episodes[i].ArtistId);
|
||||
seriesDict[series.Id] = series;
|
||||
var series = track.Artist ?? artistDict.GetValueOrDefault(tracks[i].ArtistId) ?? _artistService.GetArtist(tracks[i].ArtistId);
|
||||
artistDict[series.Id] = series;
|
||||
|
||||
if (includeSeries)
|
||||
if (includeArtist)
|
||||
{
|
||||
resource.Artist = series.ToResource();
|
||||
}
|
||||
if (includeEpisodeFile && episodes[i].TrackFileId != 0)
|
||||
if (includeTrackFile && tracks[i].TrackFileId != 0)
|
||||
{
|
||||
resource.TrackFile = episodes[i].TrackFile.Value.ToResource(series, _upgradableSpecification);
|
||||
resource.TrackFile = tracks[i].TrackFile.Value.ToResource(series, _upgradableSpecification);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,28 +105,31 @@ namespace Lidarr.Api.V1.Tracks
|
||||
return result;
|
||||
}
|
||||
|
||||
//public void Handle(EpisodeGrabbedEvent message)
|
||||
//{
|
||||
// foreach (var episode in message.Episode.Episodes)
|
||||
// {
|
||||
// var resource = episode.ToResource();
|
||||
// resource.Grabbed = true;
|
||||
public void Handle(TrackInfoRefreshedEvent message)
|
||||
{
|
||||
foreach (var track in message.Removed)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Deleted, track.ToResource());
|
||||
}
|
||||
|
||||
// BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
// }
|
||||
//}
|
||||
foreach (var track in message.Added)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, track.ToResource());
|
||||
}
|
||||
|
||||
//public void Handle(EpisodeImportedEvent message)
|
||||
//{
|
||||
// if (!message.NewDownload)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
foreach (var track in message.Updated)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, track.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(TrackImportedEvent message)
|
||||
{
|
||||
foreach (var track in message.TrackInfo.Tracks)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, track.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// foreach (var episode in message.EpisodeInfo.Episodes)
|
||||
// {
|
||||
// BroadcastResourceChange(ModelAction.Updated, episode.Id);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace NzbDrone.Common.Cloud
|
||||
Services = new HttpRequestBuilder("https://services.lidarr.audio/v1/")
|
||||
.CreateFactory();
|
||||
|
||||
Search = new HttpRequestBuilder("https://api.lidarr.audio/api/v0/{route}/") // TODO: Add {version} once LidarrAPI.Metadata is released.
|
||||
Search = new HttpRequestBuilder("https://api.lidarr.audio/api/v0.3/{route}")
|
||||
.CreateFactory();
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
_remoteAlbum.Albums = Builder<Album>.CreateListOfSize(1).Build().ToList();
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(new List<TrackFile> { });
|
||||
|
||||
Mocker.GetMock<IDelayProfileService>()
|
||||
@@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
private void GivenExistingFile(QualityModel quality, Language language)
|
||||
{
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(s => s.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(new List<TrackFile> { new TrackFile {
|
||||
Quality = quality,
|
||||
Language = language
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
private void SetupMediaFile(List<TrackFile> files)
|
||||
{
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(v => v.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(v => v.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(files);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(new List<TrackFile> { _firstFile, _secondFile });
|
||||
|
||||
_parseResultMulti = new RemoteAlbum
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(new List<TrackFile> { _firstFile, _secondFile });
|
||||
|
||||
_parseResultMulti = new RemoteAlbum
|
||||
@@ -78,7 +78,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
public void should_return_true_if_album_has_no_existing_file()
|
||||
{
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Setup(c => c.GetFilesByAlbum(It.IsAny<int>()))
|
||||
.Returns(new List<TrackFile> { });
|
||||
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
|
||||
15
src/NzbDrone.Core/Datastore/Migration/009_album_releases.cs
Normal file
15
src/NzbDrone.Core/Datastore/Migration/009_album_releases.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(9)]
|
||||
public class album_releases : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Albums").AddColumn("Releases").AsString().WithDefaultValue("").Nullable();
|
||||
Alter.Table("Albums").AddColumn("CurrentRelease").AsString().WithDefaultValue("").Nullable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (trackFiles.Any())
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (trackFiles.Any())
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
}
|
||||
|
||||
var missingTrackFiles = subject.Albums
|
||||
.SelectMany(v => _albumService.GetFilesByAlbum(v.ArtistId, v.Id))
|
||||
.SelectMany(v => _albumService.GetFilesByAlbum(v.Id))
|
||||
.DistinctBy(v => v.Id)
|
||||
.Where(v => IsTrackFileMissing(subject.Artist, v))
|
||||
.ToArray();
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (trackFiles.Any())
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.ArtistId, album.Id);
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (trackFiles.Any())
|
||||
{
|
||||
|
||||
31
src/NzbDrone.Core/Exceptions/AlbumNotFoundException.cs
Normal file
31
src/NzbDrone.Core/Exceptions/AlbumNotFoundException.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using NzbDrone.Common.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Exceptions
|
||||
{
|
||||
public class AlbumNotFoundException : NzbDroneException
|
||||
{
|
||||
public string MusicBrainzId { get; set; }
|
||||
|
||||
public AlbumNotFoundException(string musicbrainzId)
|
||||
: base(string.Format("Album with MusicBrainz {0} was not found, it may have been removed from MusicBrainz.", musicbrainzId))
|
||||
{
|
||||
MusicBrainzId = musicbrainzId;
|
||||
}
|
||||
|
||||
public AlbumNotFoundException(string musicbrainzId, string message, params object[] args)
|
||||
: base(message, args)
|
||||
{
|
||||
MusicBrainzId = musicbrainzId;
|
||||
}
|
||||
|
||||
public AlbumNotFoundException(string musicbrainzId, string message)
|
||||
: base(message)
|
||||
{
|
||||
MusicBrainzId = musicbrainzId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
void Update(List<TrackFile> trackFile);
|
||||
void Delete(TrackFile trackFile, DeleteMediaFileReason reason);
|
||||
List<TrackFile> GetFilesByArtist(int artistId);
|
||||
List<TrackFile> GetFilesByAlbum(int artistId, int albumId);
|
||||
List<TrackFile> GetFilesByAlbum(int albumId);
|
||||
List<TrackFile> GetFiles(IEnumerable<int> ids);
|
||||
List<TrackFile> GetFilesWithoutMediaInfo();
|
||||
List<string> FilterExistingFiles(List<string> files, Artist artist);
|
||||
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
}
|
||||
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<ArtistDeletedEvent>
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<ArtistDeletedEvent>, IHandleAsync<AlbumDeletedEvent>
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IMediaFileRepository _mediaFileRepository;
|
||||
@@ -104,12 +104,18 @@ namespace NzbDrone.Core.MediaFiles
|
||||
_mediaFileRepository.DeleteMany(files);
|
||||
}
|
||||
|
||||
public void HandleAsync(AlbumDeletedEvent message)
|
||||
{
|
||||
var files = GetFilesByAlbum(message.Album.Id);
|
||||
_mediaFileRepository.DeleteMany(files);
|
||||
}
|
||||
|
||||
public List<TrackFile> GetFilesByArtist(int artistId)
|
||||
{
|
||||
return _mediaFileRepository.GetFilesByArtist(artistId);
|
||||
}
|
||||
|
||||
public List<TrackFile> GetFilesByAlbum(int artistId, int albumId)
|
||||
public List<TrackFile> GetFilesByAlbum(int albumId)
|
||||
{
|
||||
return _mediaFileRepository.GetFilesByAlbum(albumId);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
var artist = _artistService.GetArtist(artistId);
|
||||
var tracks = _trackService.GetTracksByAlbum(albumId);
|
||||
var files = _mediaFileService.GetFilesByAlbum(artistId, albumId);
|
||||
var files = _mediaFileService.GetFilesByAlbum(albumId);
|
||||
|
||||
return GetPreviews(artist, tracks, files)
|
||||
.OrderByDescending(e => e.TrackNumbers.First()).ToList();
|
||||
|
||||
11
src/NzbDrone.Core/MetadataSource/IProvideAlbumInfo.cs
Normal file
11
src/NzbDrone.Core/MetadataSource/IProvideAlbumInfo.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using NzbDrone.Core.Music;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource
|
||||
{
|
||||
public interface IProvideAlbumInfo
|
||||
{
|
||||
Tuple<Album, List<Track>> GetAlbumInfo(string lidarrId, string releaseId);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
public List<string> SecondaryTypes { get; set; }
|
||||
public List<MediumResource> Media { get; set; }
|
||||
public List<TrackResource> Tracks { get; set; }
|
||||
public List<ReleaseResource> Releases { get; set; }
|
||||
public string SelectedRelease { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class ReleaseResource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Label {get; set;}
|
||||
public List<string> Country { get; set; }
|
||||
public string Format { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,13 @@ using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Core.Music;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Core.Profiles.Metadata;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
{
|
||||
public class SkyHookProxy : IProvideArtistInfo, ISearchForNewArtist
|
||||
public class SkyHookProxy : IProvideArtistInfo, ISearchForNewArtist, IProvideAlbumInfo
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly Logger _logger;
|
||||
@@ -28,9 +25,13 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IMetadataProfileService _metadataProfileService;
|
||||
|
||||
private IHttpRequestBuilderFactory customerRequestBuilder;
|
||||
private IHttpRequestBuilderFactory _customerRequestBuilder;
|
||||
|
||||
public SkyHookProxy(IHttpClient httpClient, ILidarrCloudRequestBuilder requestBuilder, IArtistService artistService, Logger logger, IConfigService configService, IMetadataProfileService metadataProfileService)
|
||||
public SkyHookProxy(IHttpClient httpClient,
|
||||
ILidarrCloudRequestBuilder requestBuilder,
|
||||
IArtistService artistService, Logger logger,
|
||||
IConfigService configService,
|
||||
IMetadataProfileService metadataProfileService)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_configService = configService;
|
||||
@@ -52,8 +53,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
var primaryTypes = metadataProfile.PrimaryAlbumTypes.Where(s => s.Allowed).Select(s => s.PrimaryAlbumType.Name);
|
||||
var secondaryTypes = metadataProfile.SecondaryAlbumTypes.Where(s => s.Allowed).Select(s => s.SecondaryAlbumType.Name);
|
||||
|
||||
var httpRequest = customerRequestBuilder.Create()
|
||||
.SetSegment("route", "artists/" + foreignArtistId)
|
||||
var httpRequest = _customerRequestBuilder.Create()
|
||||
.SetSegment("route", "artist/" + foreignArtistId)
|
||||
.AddQueryParam("primTypes", string.Join("|", primaryTypes))
|
||||
.AddQueryParam("secTypes", string.Join("|", secondaryTypes))
|
||||
.Build();
|
||||
@@ -86,16 +87,55 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
return new Tuple<Artist, List<Album>>(artist, albums.ToList());
|
||||
}
|
||||
|
||||
public Tuple<Album, List<Track>> GetAlbumInfo(string foreignAlbumId, string releaseId)
|
||||
{
|
||||
_logger.Debug("Getting Album with LidarrAPI.MetadataID of {0}", foreignAlbumId);
|
||||
|
||||
SetCustomProvider();
|
||||
|
||||
var httpRequest = _customerRequestBuilder.Create()
|
||||
.SetSegment("route", "album/" + foreignAlbumId)
|
||||
.AddQueryParam("release", releaseId ?? string.Empty)
|
||||
.Build();
|
||||
|
||||
httpRequest.AllowAutoRedirect = true;
|
||||
httpRequest.SuppressHttpError = true;
|
||||
|
||||
var httpResponse = _httpClient.Get<AlbumResource>(httpRequest);
|
||||
|
||||
|
||||
if (httpResponse.HasHttpError)
|
||||
{
|
||||
if (httpResponse.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
throw new AlbumNotFoundException(foreignAlbumId);
|
||||
}
|
||||
else if (httpResponse.StatusCode == HttpStatusCode.BadRequest)
|
||||
{
|
||||
throw new BadRequestException(foreignAlbumId);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpException(httpRequest, httpResponse);
|
||||
}
|
||||
}
|
||||
|
||||
var tracks = httpResponse.Resource.Tracks.Select(MapTrack);
|
||||
var album = MapAlbum(httpResponse.Resource);
|
||||
|
||||
return new Tuple<Album, List<Track>>(album, tracks.ToList());
|
||||
}
|
||||
|
||||
public List<Artist> SearchForNewArtist(string title)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lowerTitle = title.ToLowerInvariant();
|
||||
Console.WriteLine("Searching for " + lowerTitle);
|
||||
|
||||
if (lowerTitle.StartsWith("lidarr:") || lowerTitle.StartsWith("lidarrid:"))
|
||||
{
|
||||
var slug = lowerTitle.Split(':')[1].Trim();
|
||||
|
||||
Guid searchGuid;
|
||||
|
||||
bool isValid = Guid.TryParse(slug, out searchGuid);
|
||||
@@ -118,10 +158,12 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
|
||||
SetCustomProvider();
|
||||
|
||||
var httpRequest = customerRequestBuilder.Create()
|
||||
var httpRequest = _customerRequestBuilder.Create()
|
||||
.SetSegment("route", "search")
|
||||
.AddQueryParam("type", "artist")
|
||||
.AddQueryParam("query", title.ToLower().Trim())
|
||||
//.AddQueryParam("images","false") // Should pass these on import search to avoid looking to fanart and wiki
|
||||
//.AddQueryParam("overview","false")
|
||||
.Build();
|
||||
|
||||
|
||||
@@ -143,12 +185,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
|
||||
private Artist MapSearhResult(ArtistResource resource)
|
||||
{
|
||||
var artist = _artistService.FindById(resource.Id);
|
||||
|
||||
if (artist == null)
|
||||
{
|
||||
artist = MapArtist(resource);
|
||||
}
|
||||
var artist = _artistService.FindById(resource.Id) ?? MapArtist(resource);
|
||||
|
||||
return artist;
|
||||
}
|
||||
@@ -161,37 +198,66 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
album.ReleaseDate = resource.ReleaseDate;
|
||||
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
||||
album.AlbumType = resource.Type;
|
||||
album.Images = resource.Images.Select(MapImage).ToList();
|
||||
album.Label = resource.Labels;
|
||||
|
||||
if (resource.Images != null)
|
||||
{
|
||||
album.Images = resource.Images.Select(MapImage).ToList();
|
||||
}
|
||||
|
||||
album.Label = resource.Labels;
|
||||
album.Media = resource.Media.Select(MapMedium).ToList();
|
||||
album.Tracks = resource.Tracks.Select(MapTrack).ToList();
|
||||
album.SecondaryTypes = resource.SecondaryTypes.Select(MapSecondaryTypes).ToList();
|
||||
|
||||
if (resource.Releases != null)
|
||||
{
|
||||
album.Releases = resource.Releases.Select(MapAlbumRelease).ToList();
|
||||
album.CurrentRelease = album.Releases.FirstOrDefault(s => s.Id == resource.SelectedRelease);
|
||||
}
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
private static Medium MapMedium(MediumResource resource)
|
||||
{
|
||||
Medium medium = new Medium();
|
||||
medium.Name = resource.Name;
|
||||
medium.Number = resource.Position;
|
||||
medium.Format = resource.Format;
|
||||
Medium medium = new Medium
|
||||
{
|
||||
Name = resource.Name,
|
||||
Number = resource.Position,
|
||||
Format = resource.Format
|
||||
};
|
||||
|
||||
return medium;
|
||||
}
|
||||
|
||||
private static AlbumRelease MapAlbumRelease(ReleaseResource resource)
|
||||
{
|
||||
AlbumRelease albumRelease = new AlbumRelease
|
||||
{
|
||||
Id = resource.Id,
|
||||
ReleaseDate = resource.ReleaseDate,
|
||||
TrackCount = resource.TrackCount,
|
||||
Format = resource.Format,
|
||||
MediaCount = resource.MediaCount,
|
||||
Country = resource.Country,
|
||||
Disambiguation = resource.Disambiguation,
|
||||
Label = resource.Label
|
||||
};
|
||||
|
||||
return albumRelease;
|
||||
}
|
||||
|
||||
private static Track MapTrack(TrackResource resource)
|
||||
{
|
||||
Track track = new Track();
|
||||
track.Title = resource.TrackName;
|
||||
track.ForeignTrackId = resource.Id;
|
||||
track.TrackNumber = resource.TrackNumber;
|
||||
track.AbsoluteTrackNumber = resource.TrackPosition;
|
||||
track.Duration = resource.DurationMs;
|
||||
track.MediumNumber = resource.MediumNumber;
|
||||
|
||||
Track track = new Track
|
||||
{
|
||||
Title = resource.TrackName,
|
||||
ForeignTrackId = resource.Id,
|
||||
TrackNumber = resource.TrackNumber,
|
||||
AbsoluteTrackNumber = resource.TrackPosition,
|
||||
Duration = resource.DurationMs,
|
||||
MediumNumber = resource.MediumNumber
|
||||
};
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
@@ -213,7 +279,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
artist.Status = MapArtistStatus(resource.Status);
|
||||
artist.Ratings = MapRatings(resource.Rating);
|
||||
artist.Links = resource.Links.Select(MapLink).ToList();
|
||||
|
||||
return artist;
|
||||
}
|
||||
|
||||
@@ -251,14 +316,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
return ArtistStatusType.Continuing;
|
||||
}
|
||||
|
||||
private static Music.Ratings MapRatings(RatingResource rating)
|
||||
private static Ratings MapRatings(RatingResource rating)
|
||||
{
|
||||
if (rating == null)
|
||||
{
|
||||
return new Music.Ratings();
|
||||
return new Ratings();
|
||||
}
|
||||
|
||||
return new Music.Ratings
|
||||
return new Ratings
|
||||
{
|
||||
Votes = rating.Count,
|
||||
Value = rating.Value
|
||||
@@ -274,9 +339,9 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
};
|
||||
}
|
||||
|
||||
private static Music.Links MapLink(LinkResource arg)
|
||||
private static Links MapLink(LinkResource arg)
|
||||
{
|
||||
return new Music.Links
|
||||
return new Links
|
||||
{
|
||||
Url = arg.Target,
|
||||
Name = arg.Type
|
||||
@@ -337,11 +402,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
{
|
||||
if (_configService.MetadataSource.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
customerRequestBuilder = new HttpRequestBuilder(_configService.MetadataSource.TrimEnd("/") + "/{route}/").CreateFactory();
|
||||
_customerRequestBuilder = new HttpRequestBuilder(_configService.MetadataSource.TrimEnd("/") + "/{route}").CreateFactory();
|
||||
}
|
||||
else
|
||||
{
|
||||
customerRequestBuilder = _requestBuilder;
|
||||
_customerRequestBuilder = _requestBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,26 @@ namespace NzbDrone.Core.Music
|
||||
public AddArtistOptions AddOptions { get; set; }
|
||||
public Artist Artist { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
public List<AlbumRelease> Releases { get; set; }
|
||||
public AlbumRelease CurrentRelease { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}][{1}]", ForeignAlbumId, Title.NullSafe());
|
||||
}
|
||||
|
||||
public void ApplyChanges(Album otherAlbum)
|
||||
{
|
||||
|
||||
ForeignAlbumId = otherAlbum.ForeignAlbumId;
|
||||
|
||||
Tracks = otherAlbum.Tracks;
|
||||
|
||||
ProfileId = otherAlbum.ProfileId;
|
||||
AddOptions = otherAlbum.AddOptions;
|
||||
Monitored = otherAlbum.Monitored;
|
||||
CurrentRelease = otherAlbum.CurrentRelease;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
src/NzbDrone.Core/Music/AlbumEditedService.cs
Normal file
25
src/NzbDrone.Core/Music/AlbumEditedService.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public class AlbumEditedService : IHandle<AlbumEditedEvent>
|
||||
{
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
|
||||
public AlbumEditedService(IManageCommandQueue commandQueueManager)
|
||||
{
|
||||
_commandQueueManager = commandQueueManager;
|
||||
}
|
||||
|
||||
public void Handle(AlbumEditedEvent message)
|
||||
{
|
||||
if (message.Album.CurrentRelease.Id != message.OldAlbum.CurrentRelease.Id)
|
||||
{
|
||||
_commandQueueManager.Push(new RefreshAlbumCommand(message.Album.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/NzbDrone.Core/Music/AlbumRelease.cs
Normal file
18
src/NzbDrone.Core/Music/AlbumRelease.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public class AlbumRelease : IEmbeddedDocument
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int MediaCount { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<string> Country { get; set; }
|
||||
public string Format { get; set; }
|
||||
public List<string> Label { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace NzbDrone.Core.Music
|
||||
List<Album> GetAlbums(IEnumerable<int> albumIds);
|
||||
List<Album> GetAlbumsByArtist(int artistId);
|
||||
Album AddAlbum(Album newAlbum);
|
||||
List<Album> AddAlbums(List<Album> newAlbums);
|
||||
Album FindById(string spotifyId);
|
||||
Album FindByTitle(int artistId, string title);
|
||||
Album FindByTitleInexact(string title);
|
||||
@@ -61,11 +62,19 @@ namespace NzbDrone.Core.Music
|
||||
public Album AddAlbum(Album newAlbum)
|
||||
{
|
||||
_albumRepository.Insert(newAlbum);
|
||||
_eventAggregator.PublishEvent(new AlbumAddedEvent(GetAlbum(newAlbum.Id)));
|
||||
//_eventAggregator.PublishEvent(new AlbumAddedEvent(GetAlbum(newAlbum.Id)));
|
||||
|
||||
return newAlbum;
|
||||
}
|
||||
|
||||
public List<Album> AddAlbums(List<Album> newAlbums)
|
||||
{
|
||||
_albumRepository.InsertMany(newAlbums);
|
||||
//_eventAggregator.PublishEvent(new AlbumsAddedEvent(newAlbums.Select(s => s.Id).ToList()));
|
||||
|
||||
return newAlbums;
|
||||
}
|
||||
|
||||
public void DeleteAlbum(int albumId, bool deleteFiles)
|
||||
{
|
||||
var album = _albumRepository.Get(albumId);
|
||||
@@ -140,11 +149,16 @@ namespace NzbDrone.Core.Music
|
||||
public void DeleteMany(List<Album> albums)
|
||||
{
|
||||
_albumRepository.DeleteMany(albums);
|
||||
|
||||
foreach (var album in albums)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new AlbumDeletedEvent(album, false));
|
||||
}
|
||||
}
|
||||
|
||||
public Album UpdateAlbum(Album album)
|
||||
{
|
||||
var storedAlbum = GetAlbum(album.Id); // Is it Id or iTunesId?
|
||||
var storedAlbum = GetAlbum(album.Id);
|
||||
|
||||
var updatedAlbum = _albumRepository.Update(album);
|
||||
_eventAggregator.PublishEvent(new AlbumEditedEvent(updatedAlbum, storedAlbum));
|
||||
|
||||
22
src/NzbDrone.Core/Music/Commands/RefreshAlbumCommand.cs
Normal file
22
src/NzbDrone.Core/Music/Commands/RefreshAlbumCommand.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Music.Commands
|
||||
{
|
||||
public class RefreshAlbumCommand : Command
|
||||
{
|
||||
public int? AlbumId { get; set; }
|
||||
|
||||
public RefreshAlbumCommand()
|
||||
{
|
||||
}
|
||||
|
||||
public RefreshAlbumCommand(int? albumId)
|
||||
{
|
||||
AlbumId = albumId;
|
||||
}
|
||||
|
||||
public override bool SendUpdatesToClient => true;
|
||||
|
||||
public override bool UpdateScheduledTask => !AlbumId.HasValue;
|
||||
}
|
||||
}
|
||||
15
src/NzbDrone.Core/Music/Events/AlbumsAddedEvent.cs
Normal file
15
src/NzbDrone.Core/Music/Events/AlbumsAddedEvent.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.Music.Events
|
||||
{
|
||||
public class AlbumsAddedEvent : IEvent
|
||||
{
|
||||
public List<int> AlbumIds { get; private set; }
|
||||
|
||||
public AlbumsAddedEvent(List<int> albumIds)
|
||||
{
|
||||
AlbumIds = albumIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -12,12 +12,14 @@ namespace NzbDrone.Core.Music.Events
|
||||
public Album Album { get; set; }
|
||||
public ReadOnlyCollection<Track> Added { get; private set; }
|
||||
public ReadOnlyCollection<Track> Updated { get; private set; }
|
||||
public ReadOnlyCollection<Track> Removed { get; private set; }
|
||||
|
||||
public TrackInfoRefreshedEvent(Album album, IList<Track> added, IList<Track> updated)
|
||||
public TrackInfoRefreshedEvent(Album album, IList<Track> added, IList<Track> updated, IList<Track> removed)
|
||||
{
|
||||
Album = album;
|
||||
Added = new ReadOnlyCollection<Track>(added);
|
||||
Updated = new ReadOnlyCollection<Track>(updated);
|
||||
Removed = new ReadOnlyCollection<Track>(removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,31 +7,104 @@ using System.Collections.Generic;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
|
||||
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
|
||||
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public interface IRefreshAlbumService
|
||||
{
|
||||
void RefreshAlbumInfo(Artist artist, IEnumerable<Album> remoteAlbums);
|
||||
void RefreshAlbumInfo(Album album);
|
||||
}
|
||||
|
||||
public class RefreshAlbumService : IRefreshAlbumService
|
||||
public class RefreshAlbumService : IRefreshAlbumService, IExecute<RefreshAlbumCommand>
|
||||
{
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IProvideAlbumInfo _albumInfo;
|
||||
private readonly IRefreshTrackService _refreshTrackService;
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly IBuildFileNames _fileNameBuilder;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RefreshAlbumService(IAlbumService albumService, IBuildFileNames fileNameBuilder, IRefreshTrackService refreshTrackService, IEventAggregator eventAggregator, Logger logger)
|
||||
public RefreshAlbumService(IAlbumService albumService,
|
||||
IArtistService artistService,
|
||||
IProvideAlbumInfo albumInfo,
|
||||
IRefreshTrackService refreshTrackService,
|
||||
ITrackService trackService,
|
||||
IBuildFileNames fileNameBuilder,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_albumService = albumService;
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
_artistService = artistService;
|
||||
_albumInfo = albumInfo;
|
||||
_refreshTrackService = refreshTrackService;
|
||||
_trackService = trackService;
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void RefreshAlbumInfo(Album album)
|
||||
{
|
||||
_logger.ProgressInfo("Updating Info for {0}", album.Title);
|
||||
|
||||
Tuple<Album, List<Track>> tuple;
|
||||
|
||||
try
|
||||
{
|
||||
tuple = _albumInfo.GetAlbumInfo(album.ForeignAlbumId, album.CurrentRelease.Id);
|
||||
}
|
||||
catch (AlbumNotFoundException)
|
||||
{
|
||||
_logger.Error(
|
||||
"Album '{0}' (LidarrAPI {1}) was not found, it may have been removed from Metadata sources.",
|
||||
album.Title, album.ForeignAlbumId);
|
||||
return;
|
||||
}
|
||||
|
||||
var albumInfo = tuple.Item1;
|
||||
|
||||
if (album.ForeignAlbumId != albumInfo.ForeignAlbumId)
|
||||
{
|
||||
_logger.Warn(
|
||||
"Album '{0}' (Album {1}) was replaced with '{2}' (LidarrAPI {3}), because the original was a duplicate.",
|
||||
album.Title, album.ForeignAlbumId, albumInfo.Title, albumInfo.ForeignAlbumId);
|
||||
album.ForeignAlbumId = albumInfo.ForeignAlbumId;
|
||||
}
|
||||
|
||||
album.LastInfoSync = DateTime.UtcNow;
|
||||
album.CleanTitle = albumInfo.CleanTitle;
|
||||
album.Title = albumInfo.Title ?? "Unknown";
|
||||
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
||||
album.AlbumType = albumInfo.AlbumType;
|
||||
album.SecondaryTypes = albumInfo.SecondaryTypes;
|
||||
album.Genres = albumInfo.Genres;
|
||||
album.Media = albumInfo.Media;
|
||||
album.Label = albumInfo.Label;
|
||||
album.Images = albumInfo.Images;
|
||||
album.ReleaseDate = albumInfo.ReleaseDate;
|
||||
album.Duration = tuple.Item2.Sum(track => track.Duration);
|
||||
album.Releases = albumInfo.Releases;
|
||||
|
||||
_refreshTrackService.RefreshTrackInfo(album, tuple.Item2);
|
||||
|
||||
_albumService.UpdateAlbum(album);
|
||||
|
||||
}
|
||||
|
||||
public void RefreshAlbumInfo(Artist artist, IEnumerable<Album> remoteAlbums)
|
||||
{
|
||||
_logger.Info("Starting album info refresh for: {0}", artist);
|
||||
@@ -42,67 +115,80 @@ namespace NzbDrone.Core.Music
|
||||
|
||||
var updateList = new List<Album>();
|
||||
var newList = new List<Album>();
|
||||
var dupeFreeRemoteAlbums = remoteAlbums.DistinctBy(m => new { m.ForeignAlbumId, m.ReleaseDate }).ToList();
|
||||
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);
|
||||
|
||||
Tuple<Album, List<Track>> tuple;
|
||||
var albumInfo = new Album();
|
||||
|
||||
if (albumToUpdate != null)
|
||||
{
|
||||
|
||||
tuple = _albumInfo.GetAlbumInfo(album.ForeignAlbumId, albumToUpdate.CurrentRelease.Id);
|
||||
albumInfo = tuple.Item1;
|
||||
existingAlbums.Remove(albumToUpdate);
|
||||
updateList.Add(albumToUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
albumToUpdate = new Album();
|
||||
albumToUpdate.Monitored = artist.Monitored;
|
||||
albumToUpdate.ProfileId = artist.ProfileId;
|
||||
albumToUpdate.Added = DateTime.UtcNow;
|
||||
tuple = _albumInfo.GetAlbumInfo(album.ForeignAlbumId, null);
|
||||
albumInfo = tuple.Item1;
|
||||
albumToUpdate = new Album
|
||||
{
|
||||
Monitored = artist.Monitored,
|
||||
ProfileId = artist.ProfileId,
|
||||
Added = DateTime.UtcNow
|
||||
};
|
||||
|
||||
albumToUpdate.ArtistId = artist.Id;
|
||||
albumToUpdate.CleanTitle = albumInfo.CleanTitle;
|
||||
albumToUpdate.ForeignAlbumId = albumInfo.ForeignAlbumId;
|
||||
albumToUpdate.Title = albumInfo.Title ?? "Unknown";
|
||||
albumToUpdate.AlbumType = albumInfo.AlbumType;
|
||||
|
||||
_albumService.AddAlbum(albumToUpdate);
|
||||
|
||||
newList.Add(albumToUpdate);
|
||||
}
|
||||
|
||||
|
||||
albumToUpdate.ForeignAlbumId = album.ForeignAlbumId;
|
||||
|
||||
|
||||
albumToUpdate.LastInfoSync = DateTime.UtcNow;
|
||||
albumToUpdate.CleanTitle = album.CleanTitle;
|
||||
albumToUpdate.Title = album.Title ?? "Unknown";
|
||||
albumToUpdate.CleanTitle = albumInfo.CleanTitle;
|
||||
albumToUpdate.Title = albumInfo.Title ?? "Unknown";
|
||||
albumToUpdate.CleanTitle = Parser.Parser.CleanArtistName(albumToUpdate.Title);
|
||||
albumToUpdate.ArtistId = artist.Id;
|
||||
albumToUpdate.AlbumType = album.AlbumType;
|
||||
albumToUpdate.SecondaryTypes = album.SecondaryTypes;
|
||||
albumToUpdate.Genres = album.Genres;
|
||||
albumToUpdate.Media = album.Media;
|
||||
albumToUpdate.Label = album.Label;
|
||||
albumToUpdate.Images = album.Images;
|
||||
albumToUpdate.ReleaseDate = album.ReleaseDate;
|
||||
albumToUpdate.Duration = album.Tracks.Sum(track => track.Duration);
|
||||
albumToUpdate.AlbumType = albumInfo.AlbumType;
|
||||
albumToUpdate.SecondaryTypes = albumInfo.SecondaryTypes;
|
||||
albumToUpdate.Genres = albumInfo.Genres;
|
||||
albumToUpdate.Media = albumInfo.Media;
|
||||
albumToUpdate.Label = albumInfo.Label;
|
||||
albumToUpdate.Images = albumInfo.Images;
|
||||
albumToUpdate.ReleaseDate = albumInfo.ReleaseDate;
|
||||
albumToUpdate.Duration = tuple.Item2.Sum(track => track.Duration);
|
||||
albumToUpdate.Releases = albumInfo.Releases;
|
||||
albumToUpdate.CurrentRelease = albumInfo.CurrentRelease;
|
||||
|
||||
_refreshTrackService.RefreshTrackInfo(albumToUpdate, tuple.Item2);
|
||||
|
||||
successCount++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Fatal(e, "An error has occurred while updating track info for artist {0}. {1}", artist, album);
|
||||
_logger.Fatal(e, "An error has occurred while updating album 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);
|
||||
|
||||
_albumService.UpdateMany(newList);
|
||||
|
||||
_eventAggregator.PublishEvent(new AlbumInfoRefreshedEvent(artist, newList, updateList));
|
||||
|
||||
if (failCount != 0)
|
||||
@@ -125,13 +211,26 @@ namespace NzbDrone.Core.Music
|
||||
|
||||
private Album GetAlbumToUpdate(Artist artist, Album album, List<Album> existingAlbums)
|
||||
{
|
||||
return existingAlbums.FirstOrDefault(e => e.ForeignAlbumId == album.ForeignAlbumId/* && e.ReleaseDate == album.ReleaseDate*/);
|
||||
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);
|
||||
}
|
||||
|
||||
public void Execute(RefreshAlbumCommand message)
|
||||
{
|
||||
if (message.AlbumId.HasValue)
|
||||
{
|
||||
var album = _albumService.GetAlbum(message.AlbumId.Value);
|
||||
var artist = _artistService.GetArtist(album.ArtistId);
|
||||
RefreshAlbumInfo(album);
|
||||
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace NzbDrone.Core.Music
|
||||
{
|
||||
private readonly IProvideArtistInfo _artistInfo;
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IAlbumService _albumService;
|
||||
private readonly IRefreshAlbumService _refreshAlbumService;
|
||||
private readonly IRefreshTrackService _refreshTrackService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
@@ -29,6 +30,7 @@ namespace NzbDrone.Core.Music
|
||||
|
||||
public RefreshArtistService(IProvideArtistInfo artistInfo,
|
||||
IArtistService artistService,
|
||||
IAlbumService albumService,
|
||||
IRefreshAlbumService refreshAlbumService,
|
||||
IRefreshTrackService refreshTrackService,
|
||||
IEventAggregator eventAggregator,
|
||||
@@ -38,6 +40,7 @@ namespace NzbDrone.Core.Music
|
||||
{
|
||||
_artistInfo = artistInfo;
|
||||
_artistService = artistService;
|
||||
_albumService = albumService;
|
||||
_refreshAlbumService = refreshAlbumService;
|
||||
_refreshTrackService = refreshTrackService;
|
||||
_eventAggregator = eventAggregator;
|
||||
@@ -92,52 +95,13 @@ namespace NzbDrone.Core.Music
|
||||
{
|
||||
_logger.Warn(e, "Couldn't update artist path for " + artist.Path);
|
||||
}
|
||||
|
||||
//artist.Albums = UpdateAlbums(artist, artistInfo); # We don't need this since we don't store albums in artist table.
|
||||
|
||||
_artistService.UpdateArtist(artist);
|
||||
|
||||
_refreshAlbumService.RefreshAlbumInfo(artist, tuple.Item2);
|
||||
foreach (var album in tuple.Item2)
|
||||
{
|
||||
_refreshTrackService.RefreshTrackInfo(album, album.Tracks);
|
||||
}
|
||||
|
||||
_refreshAlbumService.RefreshAlbumInfo(artist, tuple.Item2);
|
||||
|
||||
_logger.Debug("Finished artist refresh for {0}", artist.Name);
|
||||
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
|
||||
}
|
||||
|
||||
private List<Album> UpdateAlbums(Artist artist, Artist artistInfo)
|
||||
{
|
||||
var albums = artistInfo.Albums.DistinctBy(s => s.ForeignAlbumId).ToList();
|
||||
|
||||
foreach (var album in albums)
|
||||
{
|
||||
var existingAlbum = artist.Albums.FirstOrDefault(s => s.ForeignAlbumId == album.ForeignAlbumId);
|
||||
|
||||
//Todo: Should this should use the previous season's monitored state?
|
||||
if (existingAlbum == null)
|
||||
{
|
||||
//if (album.SeasonNumber == 0)
|
||||
//{
|
||||
// album.Monitored = false;
|
||||
// continue;
|
||||
//}
|
||||
|
||||
_logger.Debug("New album ({0}) for artist: [{1}] {2}, setting monitored to true", album.Title, artist.ForeignArtistId, artist.Name);
|
||||
album.Monitored = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
album.Monitored = existingAlbum.Monitored;
|
||||
}
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
public void Execute(RefreshArtistCommand message)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new ArtistRefreshStartingEvent(message.Trigger == CommandTrigger.Manual));
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace NzbDrone.Core.Music
|
||||
trackToUpdate.AbsoluteTrackNumber = track.AbsoluteTrackNumber;
|
||||
trackToUpdate.Title = track.Title ?? "Unknown";
|
||||
trackToUpdate.AlbumId = album.Id;
|
||||
trackToUpdate.ArtistId = album.ArtistId;
|
||||
trackToUpdate.Album = track.Album ?? album;
|
||||
trackToUpdate.Explicit = track.Explicit;
|
||||
trackToUpdate.ArtistId = album.ArtistId;
|
||||
@@ -89,15 +90,11 @@ namespace NzbDrone.Core.Music
|
||||
allTracks.AddRange(newList);
|
||||
allTracks.AddRange(updateList);
|
||||
|
||||
// TODO: See if anything needs to be done here
|
||||
//AdjustMultiEpisodeAirTime(artist, allTracks);
|
||||
//AdjustDirectToDvdAirDate(artist, allTracks);
|
||||
|
||||
_trackService.DeleteMany(existingTracks);
|
||||
_trackService.UpdateMany(updateList);
|
||||
_trackService.InsertMany(newList);
|
||||
|
||||
_eventAggregator.PublishEvent(new TrackInfoRefreshedEvent(album, newList, updateList));
|
||||
_eventAggregator.PublishEvent(new TrackInfoRefreshedEvent(album, newList, updateList, existingTracks));
|
||||
|
||||
if (failCount != 0)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace NzbDrone.Core.Music
|
||||
|
||||
public class TrackService : ITrackService,
|
||||
IHandleAsync<ArtistDeletedEvent>,
|
||||
IHandleAsync<AlbumDeletedEvent>,
|
||||
IHandle<TrackFileDeletedEvent>,
|
||||
IHandle<TrackFileAddedEvent>
|
||||
{
|
||||
@@ -163,6 +164,12 @@ namespace NzbDrone.Core.Music
|
||||
_trackRepository.DeleteMany(tracks);
|
||||
}
|
||||
|
||||
public void HandleAsync(AlbumDeletedEvent message)
|
||||
{
|
||||
var tracks = GetTracksByAlbum(message.Album.Id);
|
||||
_trackRepository.DeleteMany(tracks);
|
||||
}
|
||||
|
||||
public void Handle(TrackFileDeletedEvent message)
|
||||
{
|
||||
foreach (var track in GetTracksByFileId(message.TrackFile.Id))
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
<Compile Include="Datastore\Migration\003_add_medium_support.cs" />
|
||||
<Compile Include="Datastore\Migration\006_separate_automatic_and_interactive_search.cs" />
|
||||
<Compile Include="Datastore\Migration\007_change_album_path_to_relative.cs" />
|
||||
<Compile Include="Datastore\Migration\009_album_releases.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationDbFactory.cs" />
|
||||
@@ -424,6 +425,7 @@
|
||||
<Compile Include="Download\ProcessDownloadDecisions.cs" />
|
||||
<Compile Include="Download\ProcessedDecisions.cs" />
|
||||
<Compile Include="Download\RedownloadFailedDownloadService.cs" />
|
||||
<Compile Include="Exceptions\AlbumNotFoundException.cs" />
|
||||
<Compile Include="Exceptions\ArtistNotFoundException.cs" />
|
||||
<Compile Include="Exceptions\BadRequestException.cs" />
|
||||
<Compile Include="Exceptions\DownstreamException.cs" />
|
||||
@@ -730,6 +732,7 @@
|
||||
<Compile Include="Messaging\IProcessMessage.cs" />
|
||||
<Compile Include="MetadataSource\IProvideArtistInfo.cs" />
|
||||
<Compile Include="MetadataSource\ISearchForNewArtist.cs" />
|
||||
<Compile Include="MetadataSource\IProvideAlbumInfo.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\MediumResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\MemberResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\AlbumResource.cs" />
|
||||
@@ -737,6 +740,7 @@
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\LinkResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ImageResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\RatingResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\ReleaseResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\TimeOfDayResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\Resource\TrackResource.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\SkyHookProxy.cs" />
|
||||
@@ -761,9 +765,13 @@
|
||||
<Compile Include="Extras\Metadata\MetadataRepository.cs" />
|
||||
<Compile Include="Extras\Metadata\MetadataService.cs" />
|
||||
<Compile Include="Extras\Metadata\MetadataType.cs" />
|
||||
<Compile Include="Music\AlbumEditedService.cs" />
|
||||
<Compile Include="Music\AlbumRelease.cs" />
|
||||
<Compile Include="Music\ArtistStatusType.cs" />
|
||||
<Compile Include="Music\AlbumCutoffService.cs" />
|
||||
<Compile Include="Music\Commands\BulkMoveArtistCommand.cs" />
|
||||
<Compile Include="Music\Commands\RefreshAlbumCommand.cs" />
|
||||
<Compile Include="Music\Events\AlbumsAddedEvent.cs" />
|
||||
<Compile Include="Music\Events\ArtistsImportedEvent.cs" />
|
||||
<Compile Include="Music\SecondaryAlbumType.cs" />
|
||||
<Compile Include="Music\PrimaryAlbumType.cs" />
|
||||
|
||||
@@ -237,15 +237,6 @@ namespace NzbDrone.Integration.Test
|
||||
changed = true;
|
||||
}
|
||||
|
||||
result.Albums.ForEach(season =>
|
||||
{
|
||||
if (season.Monitored != monitored.Value)
|
||||
{
|
||||
season.Monitored = monitored.Value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed)
|
||||
{
|
||||
Artist.Put(result);
|
||||
|
||||
Reference in New Issue
Block a user