private Artist GetArtist(ParsedAlbumInfo parsedAlbumInfo, SearchCriteriaBase searchCriteria) { Artist artist = null; if (searchCriteria != null) { if (searchCriteria.Artist.CleanName == parsedAlbumInfo.ArtistName.CleanArtistName()) { return(searchCriteria.Artist); } } artist = _artistService.FindByName(parsedAlbumInfo.ArtistName); if (artist == null) { _logger.Debug("Trying inexact artist match for {0}", parsedAlbumInfo.ArtistName); artist = _artistService.FindByNameInexact(parsedAlbumInfo.ArtistName); } if (artist == null) { _logger.Debug("No matching artist {0}", parsedAlbumInfo.ArtistName); return(null); } return(artist); }
public RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, int artistId, IEnumerable <int> albumIds) { return(new RemoteAlbum { ParsedAlbumInfo = parsedAlbumInfo, Artist = _artistService.GetArtist(artistId), Albums = _albumService.GetAlbums(albumIds) }); }
private static ParsedAlbumInfo ParseAlbumMatchCollection(MatchCollection matchCollection) { var artistName = matchCollection[0].Groups["artist"].Value.Replace('.', ' ').Replace('_', ' '); var albumTitle = matchCollection[0].Groups["album"].Value.Replace('.', ' ').Replace('_', ' '); var releaseVersion = matchCollection[0].Groups["version"].Value.Replace('.', ' ').Replace('_', ' '); artistName = RequestInfoRegex.Replace(artistName, "").Trim(' '); albumTitle = RequestInfoRegex.Replace(albumTitle, "").Trim(' '); releaseVersion = RequestInfoRegex.Replace(releaseVersion, "").Trim(' '); int releaseYear; int.TryParse(matchCollection[0].Groups["releaseyear"].Value, out releaseYear); ParsedAlbumInfo result; result = new ParsedAlbumInfo(); result.ArtistName = artistName; result.AlbumTitle = albumTitle; result.ArtistTitleInfo = GetArtistTitleInfo(result.ArtistName); result.ReleaseDate = releaseYear.ToString(); result.ReleaseVersion = releaseVersion; if (matchCollection[0].Groups["discography"].Success) { int discStart; int discEnd; int.TryParse(matchCollection[0].Groups["startyear"].Value, out discStart); int.TryParse(matchCollection[0].Groups["endyear"].Value, out discEnd); result.Discography = true; if (discStart > 0 && discEnd > 0) { result.DiscographyStart = discStart; result.DiscographyEnd = discEnd; } else if (discEnd > 0) { result.DiscographyEnd = discEnd; } result.AlbumTitle = "Discography"; } Logger.Debug("Album Parsed. {0}", result); return(result); }
public RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, SearchCriteriaBase searchCriteria = null) { var remoteAlbum = new RemoteAlbum { ParsedAlbumInfo = parsedAlbumInfo, }; var artist = GetArtist(parsedAlbumInfo, searchCriteria); if (artist == null) { return(remoteAlbum); } remoteAlbum.Artist = artist; remoteAlbum.Albums = GetAlbums(parsedAlbumInfo, artist, searchCriteria); return(remoteAlbum); }
public void should_not_fail_if_search_criteria_contains_multiple_albums_with_the_same_name() { var artist = Builder <Artist> .CreateNew().Build(); var albums = Builder <Album> .CreateListOfSize(2).All().With(x => x.Title = "IdenticalTitle").Build().ToList(); var criteria = new AlbumSearchCriteria { Artist = artist, Albums = albums }; var parsed = new ParsedAlbumInfo { AlbumTitle = "IdenticalTitle" }; Subject.GetAlbums(parsed, artist, criteria).Should().BeEquivalentTo(new List <Album>()); Mocker.GetMock <IAlbumService>() .Verify(s => s.FindByTitle(artist.ArtistMetadataId, "IdenticalTitle"), Times.Once()); }
public void Setup() { Mocker.Resolve <UpgradableSpecification>(); _parsedAlbumInfo = Builder <ParsedAlbumInfo> .CreateNew() .With(p => p.Quality = new QualityModel(Quality.FLAC, new Revision(2, 0, false))) .With(p => p.ReleaseGroup = "Lidarr") .Build(); _albums = Builder <Album> .CreateListOfSize(1) .All() .BuildList(); _trackFiles = Builder <TrackFile> .CreateListOfSize(3) .All() .With(t => t.AlbumId = _albums.First().Id) .BuildList(); Mocker.GetMock <IMediaFileService>() .Setup(c => c.GetFilesByAlbum(It.IsAny <int>())) .Returns(_trackFiles); }
public Tuple <List <LocalTrack>, List <ImportDecision <LocalTrack> > > GetLocalTracks(List <IFileInfo> musicFiles, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter) { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); var files = _mediaFileService.FilterUnchangedFiles(musicFiles, filter); var localTracks = new List <LocalTrack>(); var decisions = new List <ImportDecision <LocalTrack> >(); _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count); if (!files.Any()) { return(Tuple.Create(localTracks, decisions)); } ParsedAlbumInfo downloadClientItemInfo = null; if (downloadClientItem != null) { downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title); } int i = 1; foreach (var file in files) { _logger.ProgressInfo($"Reading file {i++}/{files.Count}"); var localTrack = new LocalTrack { DownloadClientAlbumInfo = downloadClientItemInfo, FolderTrackInfo = folderInfo, Path = file.FullName, Size = file.Length, Modified = file.LastWriteTimeUtc, FileTrackInfo = _audioTagService.ReadTags(file.FullName), AdditionalFile = false }; try { // TODO fix otherfiles? _augmentingService.Augment(localTrack, true); localTracks.Add(localTrack); } catch (AugmentingFailedException) { decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file"))); } catch (Exception e) { _logger.Error(e, "Couldn't import file. {0}", localTrack.Path); decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file"))); } } _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms"); return(Tuple.Create(localTracks, decisions)); }
public List <Album> GetAlbums(ParsedAlbumInfo parsedAlbumInfo, Artist artist, SearchCriteriaBase searchCriteria = null) { var albumTitle = parsedAlbumInfo.AlbumTitle; var result = new List <Album>(); if (parsedAlbumInfo.AlbumTitle == null) { return(new List <Album>()); } Album albumInfo = null; if (parsedAlbumInfo.Discography) { if (parsedAlbumInfo.DiscographyStart > 0) { return(_albumService.ArtistAlbumsBetweenDates(artist, new DateTime(parsedAlbumInfo.DiscographyStart, 1, 1), new DateTime(parsedAlbumInfo.DiscographyEnd, 12, 31), false)); } if (parsedAlbumInfo.DiscographyEnd > 0) { return(_albumService.ArtistAlbumsBetweenDates(artist, new DateTime(1800, 1, 1), new DateTime(parsedAlbumInfo.DiscographyEnd, 12, 31), false)); } return(_albumService.GetAlbumsByArtist(artist.Id)); } if (searchCriteria != null) { albumInfo = searchCriteria.Albums.ExclusiveOrDefault(e => e.Title == albumTitle); } if (albumInfo == null) { // TODO: Search by Title and Year instead of just Title when matching albumInfo = _albumService.FindByTitle(artist.ArtistMetadataId, parsedAlbumInfo.AlbumTitle); } if (albumInfo == null) { _logger.Debug("Trying inexact album match for {0}", parsedAlbumInfo.AlbumTitle); albumInfo = _albumService.FindByTitleInexact(artist.ArtistMetadataId, parsedAlbumInfo.AlbumTitle); } if (albumInfo != null) { result.Add(albumInfo); } else { _logger.Debug("Unable to find {0}", parsedAlbumInfo); } return(result); }
public void Setup() { _artist = Builder <Artist> .CreateNew() .Build(); _album = Builder <Album> .CreateNew() .Build(); _profile = new QualityProfile { Name = "Test", Cutoff = Quality.MP3_256.Id, Items = new List <QualityProfileQualityItem> { new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_256 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_320 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.FLAC } }, }; _artist.QualityProfile = new LazyLoaded <QualityProfile>(_profile); _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedAlbumInfo = Builder <ParsedAlbumInfo> .CreateNew().Build(); _parsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256); _remoteAlbum = new RemoteAlbum(); _remoteAlbum.Albums = new List <Album> { _album }; _remoteAlbum.Artist = _artist; _remoteAlbum.ParsedAlbumInfo = _parsedAlbumInfo; _remoteAlbum.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteAlbum, new Rejection("Temp Rejected", RejectionType.Temporary)); _heldReleases = new List <PendingRelease>(); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(_heldReleases); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.AllByArtistId(It.IsAny <int>())) .Returns <int>(i => _heldReleases.Where(v => v.ArtistId == i).ToList()); Mocker.GetMock <IArtistService>() .Setup(s => s.GetArtist(It.IsAny <int>())) .Returns(_artist); Mocker.GetMock <IArtistService>() .Setup(s => s.GetArtists(It.IsAny <IEnumerable <int> >())) .Returns(new List <Artist> { _artist }); Mocker.GetMock <IParsingService>() .Setup(s => s.GetAlbums(It.IsAny <ParsedAlbumInfo>(), _artist, null)) .Returns(new List <Album> { _album }); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisions(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
public List <ImportDecision <LocalTrack> > GetImportDecisions(List <IFileInfo> musicFiles, Artist artist, Album album, AlbumRelease albumRelease, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter, bool newDownload, bool singleRelease, bool includeExisting) { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); var files = filter != FilterFilesType.None && (artist != null) ? _mediaFileService.FilterUnchangedFiles(musicFiles, artist, filter) : musicFiles; var localTracks = new List <LocalTrack>(); var decisions = new List <ImportDecision <LocalTrack> >(); _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count); if (!files.Any()) { return(decisions); } ParsedAlbumInfo downloadClientItemInfo = null; if (downloadClientItem != null) { downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title); } foreach (var file in files) { var localTrack = new LocalTrack { Artist = artist, Album = album, DownloadClientAlbumInfo = downloadClientItemInfo, FolderTrackInfo = folderInfo, Path = file.FullName, Size = file.Length, Modified = file.LastWriteTimeUtc, FileTrackInfo = _audioTagService.ReadTags(file.FullName), ExistingFile = !newDownload, AdditionalFile = false }; try { // TODO fix otherfiles? _augmentingService.Augment(localTrack, true); localTracks.Add(localTrack); } catch (AugmentingFailedException) { decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file"))); } catch (Exception e) { _logger.Error(e, "Couldn't import file. {0}", localTrack.Path); decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file"))); } } _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms"); var releases = _identificationService.Identify(localTracks, artist, album, albumRelease, newDownload, singleRelease, includeExisting); foreach (var release in releases) { release.NewDownload = newDownload; var releaseDecision = GetDecision(release); foreach (var localTrack in release.LocalTracks) { if (releaseDecision.Approved) { decisions.AddIfNotNull(GetDecision(localTrack)); } else { decisions.Add(new ImportDecision <LocalTrack>(localTrack, releaseDecision.Rejections.ToArray())); } } } return(decisions); }
private IEnumerable <DownloadDecision> GetAlbumDecisions(List <ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null) { if (reports.Any()) { _logger.ProgressInfo("Processing {0} releases", reports.Count); } else { _logger.ProgressInfo("No results found"); } var reportNumber = 1; foreach (var report in reports) { DownloadDecision decision = null; _logger.ProgressTrace("Processing release {0}/{1}", reportNumber, reports.Count); _logger.Debug("Processing release '{0}' from '{1}'", report.Title, report.Indexer); try { var parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(report.Title); if (parsedAlbumInfo == null && searchCriteria != null) { parsedAlbumInfo = Parser.Parser.ParseAlbumTitleWithSearchCriteria(report.Title, searchCriteria.Artist, searchCriteria.Albums); } if (parsedAlbumInfo != null) { // TODO: Artist Data Augment without calling to parse title again //if (!report.Artist.IsNullOrWhiteSpace()) //{ // if (parsedAlbumInfo.ArtistName.IsNullOrWhiteSpace() || _parsingService.GetArtist(parsedAlbumInfo.ArtistName) == null) // { // parsedAlbumInfo.ArtistName = report.Artist; // } //} // TODO: Replace Parsed AlbumTitle with metadata Title if Parsed AlbumTitle not a valid match //if (!report.Album.IsNullOrWhiteSpace()) //{ // parsedAlbumInfo.AlbumTitle = report.Album; //} if (!parsedAlbumInfo.ArtistName.IsNullOrWhiteSpace()) { var remoteAlbum = _parsingService.Map(parsedAlbumInfo, searchCriteria); // try parsing again using the search criteria, in case it parsed but parsed incorrectly if ((remoteAlbum.Artist == null || remoteAlbum.Albums.Empty()) && searchCriteria != null) { _logger.Debug("Artist/Album null for {0}, reparsing with search criteria", report.Title); var parsedAlbumInfoWithCriteria = Parser.Parser.ParseAlbumTitleWithSearchCriteria(report.Title, searchCriteria.Artist, searchCriteria.Albums); if (parsedAlbumInfoWithCriteria != null && parsedAlbumInfoWithCriteria.ArtistName.IsNotNullOrWhiteSpace()) { remoteAlbum = _parsingService.Map(parsedAlbumInfoWithCriteria, searchCriteria); } } remoteAlbum.Release = report; if (remoteAlbum.Artist == null) { decision = new DownloadDecision(remoteAlbum, new Rejection("Unknown Artist")); // shove in the searched artist in case of forced download in interactive search if (searchCriteria != null) { remoteAlbum.Artist = searchCriteria.Artist; remoteAlbum.Albums = searchCriteria.Albums; } } else if (remoteAlbum.Albums.Empty()) { decision = new DownloadDecision(remoteAlbum, new Rejection("Unable to parse albums from release name")); if (searchCriteria != null) { remoteAlbum.Albums = searchCriteria.Albums; } } else { _aggregationService.Augment(remoteAlbum); remoteAlbum.DownloadAllowed = remoteAlbum.Albums.Any(); decision = GetDecisionForReport(remoteAlbum, searchCriteria); } } } if (searchCriteria != null) { if (parsedAlbumInfo == null) { parsedAlbumInfo = new ParsedAlbumInfo { Quality = QualityParser.ParseQuality(report.Title, null, 0) }; } if (parsedAlbumInfo.ArtistName.IsNullOrWhiteSpace()) { var remoteAlbum = new RemoteAlbum { Release = report, ParsedAlbumInfo = parsedAlbumInfo }; decision = new DownloadDecision(remoteAlbum, new Rejection("Unable to parse release")); } } } catch (Exception e) { _logger.Error(e, "Couldn't process release."); var remoteAlbum = new RemoteAlbum { Release = report }; decision = new DownloadDecision(remoteAlbum, new Rejection("Unexpected error processing release")); } reportNumber++; if (decision != null) { if (decision.Rejections.Any()) { _logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections)); } else { _logger.Debug("Release accepted"); } yield return(decision); } } }