mirror of https://github.com/lidarr/Lidarr
Partially implemented ArtistRefreshCommand. In order to move forward, API may need to be switched to Spotify.
This commit is contained in:
parent
fa80bca2c9
commit
b481bc6e45
|
@ -55,6 +55,7 @@ namespace NzbDrone.Core.Datastore.Migration
|
|||
.WithColumn("Title").AsString().Nullable()
|
||||
.WithColumn("Ignored").AsBoolean().Nullable()
|
||||
.WithColumn("Explict").AsBoolean()
|
||||
.WithColumn("Monitored").AsBoolean()
|
||||
.WithColumn("TrackExplicitName").AsString().Nullable()
|
||||
.WithColumn("TrackCensoredName").AsString().Nullable()
|
||||
.WithColumn("TrackFileId").AsInt32().Nullable()
|
||||
|
|
|
@ -16,6 +16,7 @@ using NzbDrone.Core.Messaging.Commands;
|
|||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv.Commands;
|
||||
using NzbDrone.Core.Update.Commands;
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
|
@ -64,9 +65,10 @@ namespace NzbDrone.Core.Jobs
|
|||
new ScheduledTask{ Interval = 1, TypeName = typeof(CheckForFinishedDownloadCommand).FullName},
|
||||
new ScheduledTask{ Interval = 5, TypeName = typeof(MessagingCleanupCommand).FullName},
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(ApplicationUpdateCommand).FullName},
|
||||
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||
//new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(CheckHealthCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshArtistCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName}, // TODO: Remove
|
||||
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 7*24*60, TypeName = typeof(BackupCommand).FullName},
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId)
|
||||
{
|
||||
Console.WriteLine("[GetSeriesInfo] id:" + tvdbSeriesId);
|
||||
|
@ -165,6 +167,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||
|
||||
public Tuple<Artist, List<Track>> GetArtistInfo(int itunesId)
|
||||
{
|
||||
// TODO: [GetArtistInfo]: This needs to return a set of tracks from iTunes.
|
||||
// This call is expected to return information about an artist and the tracks that make up said artist.
|
||||
// To do this, we need 2-3 API calls. 1st is to gather information about the artist and the albums the artist has. This is https://itunes.apple.com/search?entity=album&id=itunesId
|
||||
// Next call is to populate the overview field and calls the internal API
|
||||
// Finally, we need to, for each album, get all tracks, which means calling this N times: https://itunes.apple.com/search?entity=musicTrack&term=artistName (id will not work)
|
||||
_logger.Debug("Getting Artist with iTunesID of {0}", itunesId);
|
||||
var httpRequest1 = _requestBuilder.Create()
|
||||
.SetSegment("route", "lookup")
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.Music
|
|||
SeriesPathValidator seriesPathValidator,
|
||||
DroneFactoryValidator droneFactoryValidator,
|
||||
SeriesAncestorValidator seriesAncestorValidator,
|
||||
ArtistSlugValidator seriesTitleSlugValidator)
|
||||
ArtistSlugValidator artistTitleSlugValidator)
|
||||
{
|
||||
RuleFor(c => c.Path).Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
|
@ -28,7 +28,7 @@ namespace NzbDrone.Core.Music
|
|||
.SetValidator(droneFactoryValidator)
|
||||
.SetValidator(seriesAncestorValidator);
|
||||
|
||||
RuleFor(c => c.ArtistSlug).SetValidator(seriesTitleSlugValidator);// TODO: Check if we are going to use a slug or artistName
|
||||
RuleFor(c => c.ArtistSlug).SetValidator(artistTitleSlugValidator);// TODO: Check if we are going to use a slug or artistName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,35 +32,19 @@ namespace NzbDrone.Core.Music
|
|||
public bool ArtistFolder { get; set; }
|
||||
public DateTime? LastInfoSync { get; set; }
|
||||
public DateTime? LastDiskSync { get; set; }
|
||||
|
||||
public int Status { get; set; } // TODO: Figure out what this is, do we need it?
|
||||
public string Path { get; set; }
|
||||
public List<MediaCover.MediaCover> Images { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public int QualityProfileId { get; set; }
|
||||
|
||||
public string RootFolderPath { get; set; }
|
||||
public DateTime Added { get; set; }
|
||||
public LazyLoaded<Profile> Profile { get; set; }
|
||||
public int ProfileId { get; set; }
|
||||
public List<Album> Albums { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
|
||||
public AddSeriesOptions AddOptions { get; set; }
|
||||
|
||||
//public string SortTitle { get; set; }
|
||||
//public SeriesStatusType Status { get; set; }
|
||||
//public int Runtime { get; set; }
|
||||
//public SeriesTypes SeriesType { get; set; }
|
||||
//public string Network { get; set; }
|
||||
//public bool UseSceneNumbering { get; set; }
|
||||
//public string TitleSlug { get; set; }
|
||||
//public int Year { get; set; }
|
||||
//public Ratings Ratings { get; set; }
|
||||
//public List<Actor> Actors { get; set; } // MOve to album?
|
||||
//public string Certification { get; set; }
|
||||
//public DateTime? FirstAired { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}][{1}]", ItunesId, ArtistName.NullSafe());
|
||||
|
@ -88,18 +72,11 @@ namespace NzbDrone.Core.Music
|
|||
ArtistFolder = otherArtist.ArtistFolder;
|
||||
AddOptions = otherArtist.AddOptions;
|
||||
|
||||
|
||||
//TODO: Implement
|
||||
ItunesId = otherArtist.ItunesId;
|
||||
|
||||
Albums = otherArtist.Albums;
|
||||
Path = otherArtist.Path;
|
||||
ProfileId = otherArtist.ProfileId;
|
||||
|
||||
AlbumFolder = otherArtist.AlbumFolder;
|
||||
Monitored = otherArtist.Monitored;
|
||||
|
||||
//SeriesType = otherArtist.SeriesType;
|
||||
RootFolderPath = otherArtist.RootFolderPath;
|
||||
Tags = otherArtist.Tags;
|
||||
AddOptions = otherArtist.AddOptions;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public class ArtistAddedHandler : IHandle<ArtistAddedEvent>
|
||||
{
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
|
||||
public ArtistAddedHandler(IManageCommandQueue commandQueueManager)
|
||||
{
|
||||
_commandQueueManager = commandQueueManager;
|
||||
}
|
||||
|
||||
public void Handle(ArtistAddedEvent message)
|
||||
{
|
||||
_commandQueueManager.Push(new RefreshArtistCommand(message.Artist.Id));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Messaging.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Music.Commands
|
||||
{
|
||||
public class RefreshArtistCommand : Command
|
||||
{
|
||||
public int? ArtistId { get; set; }
|
||||
|
||||
public RefreshArtistCommand()
|
||||
{
|
||||
}
|
||||
|
||||
public RefreshArtistCommand(int? artistId)
|
||||
{
|
||||
ArtistId = artistId;
|
||||
}
|
||||
|
||||
public override bool SendUpdatesToClient => true;
|
||||
|
||||
public override bool UpdateScheduledTask => !ArtistId.HasValue;
|
||||
}
|
||||
}
|
|
@ -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 ArtistRefreshStartingEvent : IEvent
|
||||
{
|
||||
public bool ManualTrigger { get; set; }
|
||||
|
||||
public ArtistRefreshStartingEvent(bool manualTrigger)
|
||||
{
|
||||
ManualTrigger = manualTrigger;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 TrackInfoRefreshedEvent : IEvent
|
||||
{
|
||||
public Artist Artist { get; set; }
|
||||
public ReadOnlyCollection<Track> Added { get; private set; }
|
||||
public ReadOnlyCollection<Track> Updated { get; private set; }
|
||||
|
||||
public TrackInfoRefreshedEvent(Artist artist, IList<Track> added, IList<Track> updated)
|
||||
{
|
||||
Artist = artist;
|
||||
Added = new ReadOnlyCollection<Track>(added);
|
||||
Updated = new ReadOnlyCollection<Track>(updated);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook;
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public class RefreshArtistService : IExecute<RefreshArtistCommand>
|
||||
{
|
||||
private readonly IProvideArtistInfo _artistInfo;
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IRefreshTrackService _refreshTrackService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
//private readonly IDailySeriesService _dailySeriesService;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
//private readonly ICheckIfArtistShouldBeRefreshed _checkIfArtistShouldBeRefreshed;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RefreshArtistService(IProvideArtistInfo artistInfo,
|
||||
IArtistService artistService,
|
||||
IRefreshTrackService refreshTrackService,
|
||||
IEventAggregator eventAggregator,
|
||||
IDiskScanService diskScanService,
|
||||
//ICheckIfArtistShouldBeRefreshed checkIfArtistShouldBeRefreshed,
|
||||
Logger logger)
|
||||
{
|
||||
_artistInfo = artistInfo;
|
||||
_artistService = artistService;
|
||||
_refreshTrackService = refreshTrackService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_diskScanService = diskScanService;
|
||||
//_checkIfArtistShouldBeRefreshed = checkIfArtistShouldBeRefreshed;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private void RefreshArtistInfo(Artist artist)
|
||||
{
|
||||
_logger.ProgressInfo("Updating Info for {0}", artist.ArtistName);
|
||||
|
||||
Tuple<Artist, List<Track>> tuple;
|
||||
|
||||
try
|
||||
{
|
||||
tuple = _artistInfo.GetArtistInfo(artist.ItunesId);
|
||||
}
|
||||
catch (ArtistNotFoundException)
|
||||
{
|
||||
_logger.Error("Artist '{0}' (itunesid {1}) was not found, it may have been removed from iTunes.", artist.ArtistName, artist.ItunesId);
|
||||
return;
|
||||
}
|
||||
|
||||
var artistInfo = tuple.Item1;
|
||||
|
||||
if (artist.ItunesId != artistInfo.ItunesId)
|
||||
{
|
||||
_logger.Warn("Artist '{0}' (itunes {1}) was replaced with '{2}' (itunes {3}), because the original was a duplicate.", artist.ArtistName, artist.ItunesId, artistInfo.ArtistName, artistInfo.ItunesId);
|
||||
artist.ItunesId = artistInfo.ItunesId;
|
||||
}
|
||||
|
||||
artist.ArtistName = artistInfo.ArtistName;
|
||||
artist.ArtistSlug = artistInfo.ArtistSlug;
|
||||
artist.Overview = artistInfo.Overview;
|
||||
artist.Status = artistInfo.Status;
|
||||
artist.CleanTitle = artistInfo.CleanTitle;
|
||||
artist.LastInfoSync = DateTime.UtcNow;
|
||||
artist.Images = artistInfo.Images;
|
||||
//artist.Actors = artistInfo.Actors;
|
||||
artist.Genres = artistInfo.Genres;
|
||||
|
||||
try
|
||||
{
|
||||
artist.Path = new DirectoryInfo(artist.Path).FullName;
|
||||
artist.Path = artist.Path.GetActualCasing();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warn(e, "Couldn't update artist path for " + artist.Path);
|
||||
}
|
||||
|
||||
artist.Albums = UpdateAlbums(artist, artistInfo);
|
||||
|
||||
_artistService.UpdateArtist(artist);
|
||||
_refreshTrackService.RefreshTrackInfo(artist, tuple.Item2);
|
||||
|
||||
_logger.Debug("Finished artist refresh for {0}", artist.ArtistName);
|
||||
_eventAggregator.PublishEvent(new ArtistUpdatedEvent(artist));
|
||||
}
|
||||
|
||||
private List<Album> UpdateAlbums(Artist artist, Artist artistInfo)
|
||||
{
|
||||
var albums = artistInfo.Albums.DistinctBy(s => s.AlbumId).ToList();
|
||||
|
||||
foreach (var album in albums)
|
||||
{
|
||||
var existingAlbum = artist.Albums.FirstOrDefault(s => s.AlbumId == album.AlbumId);
|
||||
|
||||
//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.ItunesId, artist.ArtistName);
|
||||
album.Monitored = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
album.Monitored = existingAlbum.Monitored;
|
||||
}
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
public void Execute(RefreshArtistCommand message)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new ArtistRefreshStartingEvent(message.Trigger == CommandTrigger.Manual));
|
||||
|
||||
if (message.ArtistId.HasValue)
|
||||
{
|
||||
var artist = _artistService.GetArtist(message.ArtistId.Value);
|
||||
RefreshArtistInfo(artist);
|
||||
}
|
||||
else
|
||||
{
|
||||
var allArtists = _artistService.GetAllArtists().OrderBy(c => c.ArtistName).ToList();
|
||||
|
||||
foreach (var artist in allArtists)
|
||||
{
|
||||
if (message.Trigger == CommandTrigger.Manual /*|| _checkIfArtistShouldBeRefreshed.ShouldRefresh(artist)*/)
|
||||
{
|
||||
try
|
||||
{
|
||||
RefreshArtistInfo(artist);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Couldn't refresh info for {0}", artist);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Skipping refresh of artist: {0}", artist.ArtistName);
|
||||
//TODO: _diskScanService.Scan(artist);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Couldn't rescan artist {0}", artist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public interface IRefreshTrackService
|
||||
{
|
||||
void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks);
|
||||
}
|
||||
|
||||
public class RefreshTrackService : IRefreshTrackService
|
||||
{
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RefreshTrackService(ITrackService trackService, IEventAggregator eventAggregator, Logger logger)
|
||||
{
|
||||
_trackService = trackService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks)
|
||||
{
|
||||
_logger.Info("Starting track info refresh for: {0}", artist);
|
||||
var successCount = 0;
|
||||
var failCount = 0;
|
||||
|
||||
var existingTracks = _trackService.GetTrackByArtist(artist.ItunesId);
|
||||
var albums = artist.Albums;
|
||||
|
||||
var updateList = new List<Track>();
|
||||
var newList = new List<Track>();
|
||||
var dupeFreeRemoteTracks = remoteTracks.DistinctBy(m => new { m.AlbumId, m.TrackNumber }).ToList();
|
||||
|
||||
foreach (var track in OrderTracks(artist, dupeFreeRemoteTracks))
|
||||
{
|
||||
try
|
||||
{
|
||||
var trackToUpdate = GetTrackToUpdate(artist, track, existingTracks);
|
||||
|
||||
if (trackToUpdate != null)
|
||||
{
|
||||
existingTracks.Remove(trackToUpdate);
|
||||
updateList.Add(trackToUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
trackToUpdate = new Track();
|
||||
trackToUpdate.Monitored = GetMonitoredStatus(track, albums);
|
||||
newList.Add(trackToUpdate);
|
||||
}
|
||||
trackToUpdate.ArtistId = artist.ItunesId; // TODO: Ensure LazyLoaded<Artist> field gets updated.
|
||||
trackToUpdate.TrackNumber = track.TrackNumber;
|
||||
trackToUpdate.Title = track.Title ?? "Unknown";
|
||||
|
||||
// TODO: Implement rest of [RefreshTrackService] fields
|
||||
|
||||
|
||||
|
||||
successCount++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Fatal(e, "An error has occurred while updating track info for artist {0}. {1}", artist, track);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
|
||||
var allTracks = new List<Track>();
|
||||
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(artist, newList, updateList));
|
||||
|
||||
if (failCount != 0)
|
||||
{
|
||||
_logger.Info("Finished track refresh for artist: {0}. Successful: {1} - Failed: {2} ",
|
||||
artist.ArtistName, successCount, failCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Finished track refresh for artist: {0}.", artist);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetMonitoredStatus(Track track, IEnumerable<Album> albums)
|
||||
{
|
||||
if (track.TrackNumber == 0 /*&& track.AlbumId != 1*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var album = albums.SingleOrDefault(c => c.AlbumId == track.AlbumId);
|
||||
return album == null || album.Monitored;
|
||||
}
|
||||
|
||||
|
||||
private Track GetTrackToUpdate(Artist artist, Track track, List<Track> existingTracks)
|
||||
{
|
||||
return existingTracks.FirstOrDefault(e => e.AlbumId == track.AlbumId && e.TrackNumber == track.TrackNumber);
|
||||
}
|
||||
|
||||
private IEnumerable<Track> OrderTracks(Artist artist, List<Track> tracks)
|
||||
{
|
||||
return tracks.OrderBy(e => e.AlbumId).ThenBy(e => e.TrackNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,8 @@ namespace NzbDrone.Core.Music
|
|||
|
||||
public int ItunesTrackId { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public LazyLoaded<Artist> ArtistsId { get; set; }
|
||||
public LazyLoaded<Artist> Artist { get; set; }
|
||||
public int ArtistId { get; set; }
|
||||
public int CompilationId { get; set; }
|
||||
public bool Compilation { get; set; }
|
||||
public int TrackNumber { get; set; }
|
||||
|
@ -28,11 +29,10 @@ namespace NzbDrone.Core.Music
|
|||
public bool Explict { get; set; }
|
||||
public string TrackExplicitName { get; set; }
|
||||
public string TrackCensoredName { get; set; }
|
||||
public string Monitored { get; set; }
|
||||
public int TrackFileId { get; set; } // JVM: Is this needed with TrackFile reference?
|
||||
public bool Monitored { get; set; }
|
||||
public int TrackFileId { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
/*public int? SceneEpisodeNumber { get; set; }
|
||||
public bool UnverifiedSceneNumbering { get; set; }
|
||||
/*
|
||||
public Ratings Ratings { get; set; } // This might be aplicable as can be pulled from IDv3 tags
|
||||
public List<MediaCover.MediaCover> Images { get; set; }*/
|
||||
|
||||
|
|
|
@ -851,14 +851,20 @@
|
|||
<Compile Include="Music\AddArtistValidator.cs" />
|
||||
<Compile Include="Music\Album.cs" />
|
||||
<Compile Include="Music\Artist.cs" />
|
||||
<Compile Include="Music\ArtistAddedHandler.cs" />
|
||||
<Compile Include="Music\ArtistNameNormalizer.cs" />
|
||||
<Compile Include="Music\ArtistSlugValidator.cs" />
|
||||
<Compile Include="Music\ArtistRepository.cs" />
|
||||
<Compile Include="Music\ArtistService.cs" />
|
||||
<Compile Include="Music\Commands\RefreshArtistCommand.cs" />
|
||||
<Compile Include="Music\Events\ArtistAddedEvent.cs" />
|
||||
<Compile Include="Music\Events\ArtistDeletedEvent.cs" />
|
||||
<Compile Include="Music\Events\ArtistEditedEvent.cs" />
|
||||
<Compile Include="Music\Events\ArtistRefreshStartingEvent.cs" />
|
||||
<Compile Include="Music\Events\ArtistUpdatedEvent.cs" />
|
||||
<Compile Include="Music\Events\TrackInfoRefreshedEvent.cs" />
|
||||
<Compile Include="Music\RefreshArtistService.cs" />
|
||||
<Compile Include="Music\RefreshTrackService.cs" />
|
||||
<Compile Include="Music\Track.cs" />
|
||||
<Compile Include="Music\TrackService.cs" />
|
||||
<Compile Include="Notifications\Join\JoinAuthException.cs" />
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="col-md-10 col-xs-9">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-xs-10">
|
||||
<a href="artist/{{artistName}}" target="_blank">
|
||||
<a href="artist/{{artistNameSlug}}" target="_blank">
|
||||
<h2>{{artistName}}</h2>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -50,6 +50,9 @@
|
|||
<div class="col-md-2 col-xs-4">
|
||||
{{> EpisodeProgressPartial }}
|
||||
</div>
|
||||
<div class="col-md-8 col-xs-10">
|
||||
Path {{path}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue