From 5fec72395ccdf072f739c366b31dbadfb47625c3 Mon Sep 17 00:00:00 2001 From: Qstick Date: Thu, 14 Sep 2017 23:33:13 -0400 Subject: [PATCH] Null Checks for Track Parsing, Parse by Title if TrackNumber is missing --- src/Lidarr.Api.V3/Albums/AlbumResource.cs | 4 +- src/Lidarr.Api.V3/Indexers/ReleaseModule.cs | 14 ++-- src/Lidarr.Api.V3/Indexers/ReleaseResource.cs | 12 +-- .../IndexerSearch/AlbumSearchService.cs | 78 ++++++++++++++++++- .../MissingAlbumSearchCommand.cs | 20 +++++ .../MissingEpisodeSearchCommand.cs | 20 ----- src/NzbDrone.Core/Music/AlbumRepository.cs | 2 +- .../Music/ArtistScannedHandler.cs | 62 +++++++++++++++ src/NzbDrone.Core/NzbDrone.Core.csproj | 3 +- src/NzbDrone.Core/Parser/Parser.cs | 2 +- src/NzbDrone.Core/Parser/ParsingService.cs | 52 ++++++------- src/NzbDrone.Core/Tv/SeriesScannedHandler.cs | 2 +- 12 files changed, 204 insertions(+), 67 deletions(-) create mode 100644 src/NzbDrone.Core/IndexerSearch/MissingAlbumSearchCommand.cs delete mode 100644 src/NzbDrone.Core/IndexerSearch/MissingEpisodeSearchCommand.cs create mode 100644 src/NzbDrone.Core/Music/ArtistScannedHandler.cs diff --git a/src/Lidarr.Api.V3/Albums/AlbumResource.cs b/src/Lidarr.Api.V3/Albums/AlbumResource.cs index 4ac54ed7a..5f1c23d0e 100644 --- a/src/Lidarr.Api.V3/Albums/AlbumResource.cs +++ b/src/Lidarr.Api.V3/Albums/AlbumResource.cs @@ -13,7 +13,7 @@ namespace Lidarr.Api.V3.Albums { public string Title { get; set; } public int ArtistId { get; set; } - public string Label { get; set; } + public string AlbumLabel { get; set; } public bool Monitored { get; set; } public string Path { get; set; } public int ProfileId { get; set; } @@ -41,7 +41,7 @@ namespace Lidarr.Api.V3.Albums { Id = model.Id, ArtistId = model.ArtistId, - Label = model.Label, + AlbumLabel = model.Label, Path = model.Path, ProfileId = model.ProfileId, Monitored = model.Monitored, diff --git a/src/Lidarr.Api.V3/Indexers/ReleaseModule.cs b/src/Lidarr.Api.V3/Indexers/ReleaseModule.cs index 68b386797..9922c661d 100644 --- a/src/Lidarr.Api.V3/Indexers/ReleaseModule.cs +++ b/src/Lidarr.Api.V3/Indexers/ReleaseModule.cs @@ -53,9 +53,9 @@ namespace Lidarr.Api.V3.Indexers private Response DownloadRelease(ReleaseResource release) { - var remoteEpisode = _remoteAlbumCache.Find(release.Guid); + var remoteAlbum = _remoteAlbumCache.Find(release.Guid); - if (remoteEpisode == null) + if (remoteAlbum == null) { _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired."); @@ -64,7 +64,7 @@ namespace Lidarr.Api.V3.Indexers try { - _downloadService.DownloadReport(remoteEpisode); + _downloadService.DownloadReport(remoteAlbum); } catch (ReleaseDownloadException ex) { @@ -77,15 +77,15 @@ namespace Lidarr.Api.V3.Indexers private List GetReleases() { - if (Request.Query.episodeId.HasValue) + if (Request.Query.albumId.HasValue) { - return GetEpisodeReleases(Request.Query.episodeId); + return GetAlbumReleases(Request.Query.albumId); } return GetRss(); } - private List GetEpisodeReleases(int albumId) + private List GetAlbumReleases(int albumId) { try { @@ -96,7 +96,7 @@ namespace Lidarr.Api.V3.Indexers } catch (Exception ex) { - _logger.ErrorException("Episode search failed: " + ex.Message, ex); + _logger.ErrorException("Album search failed: " + ex.Message, ex); } return new List(); diff --git a/src/Lidarr.Api.V3/Indexers/ReleaseResource.cs b/src/Lidarr.Api.V3/Indexers/ReleaseResource.cs index 373cf71f0..777c5ebf6 100644 --- a/src/Lidarr.Api.V3/Indexers/ReleaseResource.cs +++ b/src/Lidarr.Api.V3/Indexers/ReleaseResource.cs @@ -64,7 +64,7 @@ namespace Lidarr.Api.V3.Indexers public static ReleaseResource ToResource(this DownloadDecision model) { var releaseInfo = model.RemoteAlbum.Release; - var parsedEpisodeInfo = model.RemoteAlbum.ParsedAlbumInfo; + var parsedAlbumInfo = model.RemoteAlbum.ParsedAlbumInfo; var remoteEpisode = model.RemoteAlbum; var torrentInfo = (model.RemoteAlbum.Release as TorrentInfo) ?? new TorrentInfo(); @@ -72,7 +72,7 @@ namespace Lidarr.Api.V3.Indexers return new ReleaseResource { Guid = releaseInfo.Guid, - Quality = parsedEpisodeInfo.Quality, + Quality = parsedAlbumInfo.Quality, //QualityWeight Age = releaseInfo.Age, AgeHours = releaseInfo.AgeHours, @@ -80,14 +80,14 @@ namespace Lidarr.Api.V3.Indexers Size = releaseInfo.Size, IndexerId = releaseInfo.IndexerId, Indexer = releaseInfo.Indexer, - ReleaseGroup = parsedEpisodeInfo.ReleaseGroup, - ReleaseHash = parsedEpisodeInfo.ReleaseHash, + ReleaseGroup = parsedAlbumInfo.ReleaseGroup, + ReleaseHash = parsedAlbumInfo.ReleaseHash, Title = releaseInfo.Title, //FullSeason = parsedEpisodeInfo.FullSeason, //SeasonNumber = parsedEpisodeInfo.SeasonNumber, - Language = parsedEpisodeInfo.Language, + Language = parsedAlbumInfo.Language, //AirDate = parsedEpisodeInfo.AirDate, - ArtistName = parsedEpisodeInfo.ArtistName, + ArtistName = parsedAlbumInfo.ArtistName, //EpisodeNumbers = parsedEpisodeInfo.EpisodeNumbers, //AbsoluteEpisodeNumbers = parsedEpisodeInfo.AbsoluteEpisodeNumbers, diff --git a/src/NzbDrone.Core/IndexerSearch/AlbumSearchService.cs b/src/NzbDrone.Core/IndexerSearch/AlbumSearchService.cs index 3adee9768..f34a5422b 100644 --- a/src/NzbDrone.Core/IndexerSearch/AlbumSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/AlbumSearchService.cs @@ -1,27 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; using NLog; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Instrumentation.Extensions; +using NzbDrone.Core.Datastore; +using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Queue; +using NzbDrone.Core.Music; namespace NzbDrone.Core.IndexerSearch { - class AlbumSearchService : IExecute - //IExecute, + class AlbumSearchService : IExecute, + IExecute //IExecute { private readonly ISearchForNzb _nzbSearchService; + private readonly IAlbumService _albumService; + private readonly IQueueService _queueService; private readonly IProcessDownloadDecisions _processDownloadDecisions; private readonly Logger _logger; public AlbumSearchService(ISearchForNzb nzbSearchService, + IAlbumService albumService, + IQueueService queueService, IProcessDownloadDecisions processDownloadDecisions, Logger logger) { _nzbSearchService = nzbSearchService; + _albumService = albumService; + _queueService = queueService; _processDownloadDecisions = processDownloadDecisions; _logger = logger; } + private void SearchForMissingAlbums(List albums, bool userInvokedSearch) + { + _logger.ProgressInfo("Performing missing search for {0} albums", albums.Count); + var downloadedCount = 0; + + foreach (var album in albums) + { + List decisions; + decisions = _nzbSearchService.AlbumSearch(album.Id, false, userInvokedSearch); + var processed = _processDownloadDecisions.ProcessDecisions(decisions); + + downloadedCount += processed.Grabbed.Count; + } + + _logger.ProgressInfo("Completed missing search for {0} albums. {1} reports downloaded.", albums.Count, downloadedCount); + } + + public void Execute(AlbumSearchCommand message) { foreach (var albumId in message.AlbumIds) @@ -33,5 +65,47 @@ namespace NzbDrone.Core.IndexerSearch _logger.ProgressInfo("Album search completed. {0} reports downloaded.", processed.Grabbed.Count); } } + + public void Execute(MissingAlbumSearchCommand message) + { + List albums; + + if (message.ArtistId.HasValue) + { + int artistId = message.ArtistId.Value; + + albums = _albumService.AlbumsWithoutFiles(new PagingSpec + { + Page = 1, + PageSize = 100000, + SortDirection = SortDirection.Ascending, + SortKey = "Id", + FilterExpression = + v => + v.Monitored == true && + v.Artist.Monitored == true + }).Records.Where(e => e.ArtistId.Equals(artistId)).ToList(); + } + + else + { + albums = _albumService.AlbumsWithoutFiles(new PagingSpec + { + Page = 1, + PageSize = 100000, + SortDirection = SortDirection.Ascending, + SortKey = "Id", + FilterExpression = + v => + v.Monitored == true && + v.Artist.Monitored == true + }).Records.ToList(); + } + + var queue = _queueService.GetQueue().Select(q => q.Album.Id); + var missing = albums.Where(e => !queue.Contains(e.Id)).ToList(); + + SearchForMissingAlbums(missing, message.Trigger == CommandTrigger.Manual); + } } } diff --git a/src/NzbDrone.Core/IndexerSearch/MissingAlbumSearchCommand.cs b/src/NzbDrone.Core/IndexerSearch/MissingAlbumSearchCommand.cs new file mode 100644 index 000000000..1f4ccb7b8 --- /dev/null +++ b/src/NzbDrone.Core/IndexerSearch/MissingAlbumSearchCommand.cs @@ -0,0 +1,20 @@ +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.IndexerSearch +{ + public class MissingAlbumSearchCommand : Command + { + public int? ArtistId { get; set; } + + public override bool SendUpdatesToClient => true; + + public MissingAlbumSearchCommand() + { + } + + public MissingAlbumSearchCommand(int artistId) + { + ArtistId = artistId; + } + } +} diff --git a/src/NzbDrone.Core/IndexerSearch/MissingEpisodeSearchCommand.cs b/src/NzbDrone.Core/IndexerSearch/MissingEpisodeSearchCommand.cs deleted file mode 100644 index 3e2097be3..000000000 --- a/src/NzbDrone.Core/IndexerSearch/MissingEpisodeSearchCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using NzbDrone.Core.Messaging.Commands; - -namespace NzbDrone.Core.IndexerSearch -{ - public class MissingEpisodeSearchCommand : Command - { - public int? SeriesId { get; set; } - - public override bool SendUpdatesToClient => true; - - public MissingEpisodeSearchCommand() - { - } - - public MissingEpisodeSearchCommand(int seriesId) - { - SeriesId = seriesId; - } - } -} \ No newline at end of file diff --git a/src/NzbDrone.Core/Music/AlbumRepository.cs b/src/NzbDrone.Core/Music/AlbumRepository.cs index 51f5b869a..abc9109f0 100644 --- a/src/NzbDrone.Core/Music/AlbumRepository.cs +++ b/src/NzbDrone.Core/Music/AlbumRepository.cs @@ -174,7 +174,7 @@ namespace NzbDrone.Core.Music return Query.Where(s => s.CleanTitle == title) .AndWhere(s => s.ArtistId == artistId) - .SingleOrDefault(); + .FirstOrDefault(); } public Album FindByArtistAndName(string artistName, string cleanTitle) diff --git a/src/NzbDrone.Core/Music/ArtistScannedHandler.cs b/src/NzbDrone.Core/Music/ArtistScannedHandler.cs new file mode 100644 index 000000000..f1493c2d8 --- /dev/null +++ b/src/NzbDrone.Core/Music/ArtistScannedHandler.cs @@ -0,0 +1,62 @@ +using NLog; +using NzbDrone.Core.IndexerSearch; +using NzbDrone.Core.MediaFiles.Events; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Messaging.Events; + +namespace NzbDrone.Core.Music +{ + public class ArtistScannedHandler : IHandle, + IHandle + { + private readonly IAlbumMonitoredService _albumMonitoredService; + private readonly IArtistService _artistService; + private readonly IManageCommandQueue _commandQueueManager; + //private readonly IEpisodeAddedService _episodeAddedService; + + private readonly Logger _logger; + + public ArtistScannedHandler(IAlbumMonitoredService albumMonitoredService, + IArtistService artistService, + IManageCommandQueue commandQueueManager, + //IEpisodeAddedService episodeAddedService, + Logger logger) + { + _albumMonitoredService = albumMonitoredService; + _artistService = artistService; + _commandQueueManager = commandQueueManager; + //_episodeAddedService = episodeAddedService; + _logger = logger; + } + + private void HandleScanEvents(Artist artist) + { + if (artist.AddOptions == null) + { + //_episodeAddedService.SearchForRecentlyAdded(series.Id); + return; + } + + _logger.Info("[{0}] was recently added, performing post-add actions", artist.Name); + _albumMonitoredService.SetAlbumMonitoredStatus(artist, artist.AddOptions); + + if (artist.AddOptions.SearchForMissingTracks) + { + _commandQueueManager.Push(new MissingAlbumSearchCommand(artist.Id)); + } + + artist.AddOptions = null; + _artistService.RemoveAddOptions(artist); + } + + public void Handle(ArtistScannedEvent message) + { + HandleScanEvents(message.Artist); + } + + public void Handle(ArtistScanSkippedEvent message) + { + HandleScanEvents(message.Artist); + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 5184b5ded..6141243e7 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -697,7 +697,7 @@ - + @@ -865,6 +865,7 @@ + diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 39c386867..4df0a46ae 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -338,7 +338,7 @@ namespace NzbDrone.Core.Parser var artist = file.Tag.FirstAlbumArtist; - if (artist.IsNotNullOrWhiteSpace()) + if (artist.IsNullOrWhiteSpace()) { artist = file.Tag.FirstPerformer; } diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index 8061c4c3b..0be6198c8 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -38,8 +38,6 @@ namespace NzbDrone.Core.Parser { private readonly IEpisodeService _episodeService; private readonly ISeriesService _seriesService; - - private readonly IAlbumRepository _albumRepository; private readonly IArtistService _artistService; private readonly IAlbumService _albumService; private readonly ITrackService _trackService; @@ -49,14 +47,12 @@ namespace NzbDrone.Core.Parser ISeriesService seriesService, ITrackService trackService, IArtistService artistService, - IAlbumRepository albumRepository, IAlbumService albumService, // ISceneMappingService sceneMappingService, Logger logger) { _episodeService = episodeService; _seriesService = seriesService; - _albumRepository = albumRepository; _albumService = albumService; _artistService = artistService; // _sceneMappingService = sceneMappingService; @@ -694,11 +690,6 @@ namespace NzbDrone.Core.Parser parsedTrackInfo = Parser.ParseMusicPath(filename); } - //if (parsedTrackInfo == null) - //{ - // var title = Path.GetFileNameWithoutExtension(filename); - //} - if (parsedTrackInfo == null) { if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(filename))) @@ -734,6 +725,28 @@ namespace NzbDrone.Core.Parser { var result = new List(); + if (parsedTrackInfo.AlbumTitle.IsNullOrWhiteSpace()) + { + return new List(); + } + + var album = _albumService.FindByTitle(artist.Id, parsedTrackInfo.AlbumTitle); + + if (album == null) + { + return new List(); + } + + Track trackInfo = null; + + trackInfo = _trackService.FindTrackByTitle(artist.Id, album.Id, parsedTrackInfo.Title); + + if (trackInfo !=null) + { + result.Add(trackInfo); + return result; + } + if (parsedTrackInfo.TrackNumbers == null) { return new List(); @@ -741,26 +754,13 @@ namespace NzbDrone.Core.Parser foreach (var trackNumber in parsedTrackInfo.TrackNumbers) { - Track trackInfo = null; + Track trackInfoByNumber = null; - //if (searchCriteria != null) - //{ - // trackInfo = searchCriteria.Episodes.SingleOrDefault(e => e.SeasonNumber == seasonNumber && e.EpisodeNumber == trackNumber); - //} - - if (trackInfo == null) - { - var album = _albumRepository.FindByArtistAndName(parsedTrackInfo.ArtistTitle, Parser.CleanArtistTitle(parsedTrackInfo.AlbumTitle)); - if (album == null) - { - return new List(); - } - trackInfo = _trackService.FindTrack(artist.Id, album.Id, trackNumber); - } + trackInfoByNumber = _trackService.FindTrack(artist.Id, album.Id, trackNumber); - if (trackInfo != null) + if (trackInfoByNumber != null) { - result.Add(trackInfo); + result.Add(trackInfoByNumber); } else diff --git a/src/NzbDrone.Core/Tv/SeriesScannedHandler.cs b/src/NzbDrone.Core/Tv/SeriesScannedHandler.cs index 9d208c764..691c91c7e 100644 --- a/src/NzbDrone.Core/Tv/SeriesScannedHandler.cs +++ b/src/NzbDrone.Core/Tv/SeriesScannedHandler.cs @@ -42,7 +42,7 @@ namespace NzbDrone.Core.Tv if (series.AddOptions.SearchForMissingEpisodes) { - _commandQueueManager.Push(new MissingEpisodeSearchCommand(series.Id)); + _commandQueueManager.Push(new MissingAlbumSearchCommand(series.Id)); } series.AddOptions = null;